Merge branch 'next' into fix/wrong-container-name-for-database-proxy

This commit is contained in:
Andras Bacsai
2025-03-12 15:41:08 +01:00
committed by GitHub
105 changed files with 2279 additions and 1387 deletions

View File

@@ -2,6 +2,145 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
## [unreleased]
### 🚀 Features
- *(billing)* Add Stripe past due subscription status tracking
- *(ui)* Add past due subscription warning banner
### 🐛 Bug Fixes
- *(billing)* Restrict Stripe subscription status update to 'active' only
### 💼 Other
- Bump Coolify to 4.0.0-beta.398
### 🚜 Refactor
- *(billing)* Enhance Stripe subscription status handling and notifications
## [4.0.0-beta.397] - 2025-02-28
### 🐛 Bug Fixes
- *(billing)* Handle 'past_due' subscription status in Stripe processing
- *(revert)* Label parsing
- *(helpers)* Initialize command variable in parseCommandFromMagicEnvVariable
### 📚 Documentation
- Update changelog
## [4.0.0-beta.396] - 2025-02-28
### 🚀 Features
- *(ui)* Add wire:key to two-step confirmation settings
- *(database)* Add index to scheduled task executions for improved query performance
- *(database)* Add index to scheduled database backup executions
### 🐛 Bug Fixes
- *(core)* Production dockerfile
- *(ui)* Update storage configuration guidance link
- *(ui)* Set default SMTP encryption to starttls
- *(notifications)* Correct environment URL path in application notifications
- *(config)* Update default PostgreSQL host to coolify-db instead of postgres
- *(docker)* Improve Docker compose file validation process
- *(ui)* Restrict service retrieval to current team
- *(core)* Only validate custom compose files
- *(mail)* Set default mailer to array when not specified
- *(ui)* Correct redirect routes after task deletion
- *(core)* Adding a new server should not try to make the default docker network
- *(core)* Clean up unnecessary files during application image build
- *(core)* Improve label generation and merging for applications and services
### 💼 Other
- Bump all dependencies (#5216)
### 🚜 Refactor
- *(ui)* Simplify file storage modal confirmations
- *(notifications)* Improve transactional email settings handling
- *(scheduled-tasks)* Improve scheduled task creation and management
### 📚 Documentation
- Update changelog
- Update changelog
### ⚙️ Miscellaneous Tasks
- Bump helper and realtime version
## [4.0.0-beta.395] - 2025-02-22
### 📚 Documentation
- Update changelog
## [4.0.0-beta.394] - 2025-02-17
### 📚 Documentation
- Update changelog
## [4.0.0-beta.393] - 2025-02-15
### 📚 Documentation
- Update changelog
## [4.0.0-beta.392] - 2025-02-13
### 🚀 Features
- *(ui)* Add top padding to pricing plans view
- *(core)* Add error logging and cron parsing to docker/server schedules
- *(core)* Prevent using servers with existing resources as build servers
- *(ui)* Add textarea switching option in service compose editor
### 🐛 Bug Fixes
- Pull latest image from registry when using build server
- *(deployment)* Improve server selection for deployment cancellation
- *(deployment)* Improve log line rendering and formatting
- *(s3-storage)* Optimize team admin notification query
- *(core)* Improve connection testing with dynamic disk configuration for s3 backups
- *(core)* Update service status refresh event handling
- *(ui)* Adjust polling intervals for database and service status checks
- *(service)* Update Fider service template healthcheck command
- *(core)* Improve server selection error handling in Docker component
- *(core)* Add server functionality check before dispatching container status
- *(ui)* Disable sticky scroll in Monaco editor
- *(ui)* Add literal and multiline env support to services.
- *(services)* Owncloud docs link
- *(template)* Remove db-migration step from `infisical.yaml` (#5209)
- *(service)* Penpot (#5047)
### 🚜 Refactor
- Use pull flag on docker compose up
### 📚 Documentation
- Update changelog
- Update changelog
### ⚙️ Miscellaneous Tasks
- Rollback Coolify version to 4.0.0-beta.392
- Bump Coolify version to 4.0.0-beta.393
- Bump Coolify version to 4.0.0-beta.394
- Bump Coolify version to 4.0.0-beta.395
- Bump Coolify version to 4.0.0-beta.396
- *(services)* Update zipline to use new Database env var. (#5210)
- *(service)* Upgrade authentik service
- *(service)* Remove unused env from zipline
## [4.0.0-beta.391] - 2025-02-04 ## [4.0.0-beta.391] - 2025-02-04
### 🚀 Features ### 🚀 Features
@@ -13,6 +152,11 @@ All notable changes to this project will be documented in this file.
- *(changelog)* Add git cliff for automatic changelog generation - *(changelog)* Add git cliff for automatic changelog generation
- *(workflows)* Improve changelog generation and workflows - *(workflows)* Improve changelog generation and workflows
- *(ui)* Add periodic status checking for services - *(ui)* Add periodic status checking for services
- *(deployment)* Ensure private key is stored in filesystem before deployment
- *(slack)* Show message title in notification previews (#5063)
- *(i18n)* Add Arabic translations (#4991)
- *(i18n)* Add French translations (#4992)
- *(services)* Update `service-templates.json`
### 🐛 Bug Fixes ### 🐛 Bug Fixes
@@ -22,6 +166,17 @@ All notable changes to this project will be documented in this file.
- *(ui)* Simplify service templates loading logic - *(ui)* Simplify service templates loading logic
- *(ui)* Align title and add button vertically in various views - *(ui)* Align title and add button vertically in various views
- Handle pullrequest:updated for reliable preview deployments - Handle pullrequest:updated for reliable preview deployments
- *(ui)* Fix typo on team page (#5105)
- Cal.com documentation link give 404 (#5070)
- *(slack)* Notification settings URL in `HighDiskUsage` message (#5071)
- *(ui)* Correct typo in Storage delete dialog (#5061)
- *(lang)* Add missing italian translations (#5057)
- *(service)* Improve duplicati.yaml (#4971)
- *(service)* Links in homepage service (#5002)
- *(service)* Added SMTP credentials to getoutline yaml template file (#5011)
- *(service)* Added `KEY` Variable to Beszel Template (#5021)
- *(cloudflare-tunnels)* Dead links to docs (#5104)
- System-wide GitHub apps (#5114)
### 🚜 Refactor ### 🚜 Refactor
@@ -31,12 +186,16 @@ All notable changes to this project will be documented in this file.
- *(services)* Reword nitropage url and slogan - *(services)* Reword nitropage url and slogan
- *(readme)* Add Convex to special sponsors section - *(readme)* Add Convex to special sponsors section
- Update changelog
### ⚙️ Miscellaneous Tasks ### ⚙️ Miscellaneous Tasks
- *(config)* Increase default PHP memory limit to 256M - *(config)* Increase default PHP memory limit to 256M
- Add openapi response - Add openapi response
- *(workflows)* Make naming more clear and remove unused code - *(workflows)* Make naming more clear and remove unused code
- Bump Coolify version to 4.0.0-beta.392/393
- *(ci)* Update changelog generation workflow to target 'next' branch
- *(ci)* Update changelog generation workflow to target main branch
## [4.0.0-beta.390] - 2025-01-28 ## [4.0.0-beta.390] - 2025-01-28

View File

@@ -208,7 +208,6 @@ class GetContainersStatus
$foundServices[] = "$service->id-$service->name"; $foundServices[] = "$service->id-$service->name";
$statusFromDb = $service->status; $statusFromDb = $service->status;
if ($statusFromDb !== $containerStatus) { if ($statusFromDb !== $containerStatus) {
// ray('Updating status: ' . $containerStatus);
$service->update(['status' => $containerStatus]); $service->update(['status' => $containerStatus]);
} else { } else {
$service->update(['last_online_at' => now()]); $service->update(['last_online_at' => now()]);

View File

@@ -50,7 +50,7 @@ class CloudCleanupSubscriptions extends Command
} else { } else {
$subscription = $stripe->subscriptions->retrieve(data_get($team, 'subscription.stripe_subscription_id'), []); $subscription = $stripe->subscriptions->retrieve(data_get($team, 'subscription.stripe_subscription_id'), []);
$status = data_get($subscription, 'status'); $status = data_get($subscription, 'status');
if ($status === 'active' || $status === 'past_due') { if ($status === 'active') {
$team->subscription->update([ $team->subscription->update([
'stripe_invoice_paid' => true, 'stripe_invoice_paid' => true,
'stripe_trial_already_ended' => false, 'stripe_trial_already_ended' => false,

View File

@@ -18,6 +18,7 @@ use App\Models\Service;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Validation\Rule; use Illuminate\Validation\Rule;
use OpenApi\Attributes as OA; use OpenApi\Attributes as OA;
use Spatie\Url\Url;
use Symfony\Component\Yaml\Yaml; use Symfony\Component\Yaml\Yaml;
use Visus\Cuid2\Cuid2; use Visus\Cuid2\Cuid2;
@@ -811,6 +812,11 @@ class ApplicationsController extends Controller
'docker_compose_raw' => 'string|nullable', 'docker_compose_raw' => 'string|nullable',
'docker_compose_domains' => 'array|nullable', 'docker_compose_domains' => 'array|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); $validationRules = array_merge(sharedDataApplications(), $validationRules);
$validator = customApiValidator($request->all(), $validationRules); $validator = customApiValidator($request->all(), $validationRules);
if ($validator->fails()) { if ($validator->fails()) {
@@ -822,10 +828,6 @@ class ApplicationsController extends Controller
if (! $request->has('name')) { if (! $request->has('name')) {
$request->offsetSet('name', generate_application_name($request->git_repository, $request->git_branch)); $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); $return = $this->validateDataApplications($request, $server);
if ($return instanceof \Illuminate\Http\JsonResponse) { if ($return instanceof \Illuminate\Http\JsonResponse) {
return $return; return $return;
@@ -848,7 +850,13 @@ class ApplicationsController extends Controller
if ($dockerComposeDomainsJson->count() > 0) { if ($dockerComposeDomainsJson->count() > 0) {
$application->docker_compose_domains = $dockerComposeDomainsJson; $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 = $repository_url_parsed->getSegment(1).'/'.$repository_url_parsed->getSegment(2);
$application->fqdn = $fqdn; $application->fqdn = $fqdn;
$application->destination_id = $destination->id; $application->destination_id = $destination->id;
$application->destination_type = $destination->getMorphClass(); $application->destination_type = $destination->getMorphClass();
@@ -1291,11 +1299,6 @@ class ApplicationsController extends Controller
$dockerCompose = base64_decode($request->docker_compose_raw); $dockerCompose = base64_decode($request->docker_compose_raw);
$dockerComposeRaw = Yaml::dump(Yaml::parse($dockerCompose), 10, 2, Yaml::DUMP_MULTI_LINE_LITERAL_BLOCK); $dockerComposeRaw = Yaml::dump(Yaml::parse($dockerCompose), 10, 2, Yaml::DUMP_MULTI_LINE_LITERAL_BLOCK);
// $isValid = validateComposeFile($dockerComposeRaw, $server_id);
// if ($isValid !== 'OK') {
// return $this->dispatch('error', "Invalid docker-compose file.\n$isValid");
// }
$service = new Service; $service = new Service;
removeUnnecessaryFieldsFromRequest($request); removeUnnecessaryFieldsFromRequest($request);
$service->fill($request->all()); $service->fill($request->all());

View File

@@ -54,7 +54,7 @@ class Controller extends BaseController
'email' => Str::lower($arrayOfRequest['email']), 'email' => Str::lower($arrayOfRequest['email']),
]); ]);
$type = set_transanctional_email_settings(); $type = set_transanctional_email_settings();
if (! $type) { if (blank($type)) {
return response()->json(['message' => 'Transactional emails are not active'], 400); return response()->json(['message' => 'Transactional emails are not active'], 400);
} }
$request->validate([Fortify::email() => 'required|email']); $request->validate([Fortify::email() => 'required|email']);

View File

@@ -49,7 +49,7 @@ class Bitbucket extends Controller
$full_name = data_get($payload, 'repository.full_name'); $full_name = data_get($payload, 'repository.full_name');
$commit = data_get($payload, 'push.changes.0.new.target.hash'); $commit = data_get($payload, 'push.changes.0.new.target.hash');
if (!$branch) { if (! $branch) {
return response([ return response([
'status' => 'failed', 'status' => 'failed',
'message' => 'Nothing to do. No branch found in the request.', 'message' => 'Nothing to do. No branch found in the request.',

View File

@@ -152,7 +152,7 @@ class Gitea extends Controller
} }
} }
if ($x_gitea_event === 'pull_request') { if ($x_gitea_event === 'pull_request') {
if ($action === 'opened' || $action === 'synchronize' || $action === 'reopened') { if ($action === 'opened' || $action === 'synchronized' || $action === 'reopened') {
if ($application->isPRDeployable()) { if ($application->isPRDeployable()) {
$deployment_uuid = new Cuid2; $deployment_uuid = new Cuid2;
$found = ApplicationPreview::where('application_id', $application->id)->where('pull_request_id', $pull_request_id)->first(); $found = ApplicationPreview::where('application_id', $application->id)->where('pull_request_id', $pull_request_id)->first();
@@ -202,7 +202,6 @@ class Gitea extends Controller
if ($found) { if ($found) {
$found->delete(); $found->delete();
$container_name = generateApplicationContainerName($application, $pull_request_id); $container_name = generateApplicationContainerName($application, $pull_request_id);
// ray('Stopping container: ' . $container_name);
instant_remote_process(["docker rm -f $container_name"], $application->destination->server); instant_remote_process(["docker rm -f $container_name"], $application->destination->server);
$return_payloads->push([ $return_payloads->push([
'application' => $application->name, 'application' => $application->name,

View File

@@ -208,7 +208,6 @@ class Github extends Controller
if ($found) { if ($found) {
$found->delete(); $found->delete();
$container_name = generateApplicationContainerName($application, $pull_request_id); $container_name = generateApplicationContainerName($application, $pull_request_id);
// ray('Stopping container: ' . $container_name);
instant_remote_process(["docker rm -f $container_name"], $application->destination->server); instant_remote_process(["docker rm -f $container_name"], $application->destination->server);
$return_payloads->push([ $return_payloads->push([
'application' => $application->name, 'application' => $application->name,

View File

@@ -227,7 +227,6 @@ class Gitlab extends Controller
if ($found) { if ($found) {
$found->delete(); $found->delete();
$container_name = generateApplicationContainerName($application, $pull_request_id); $container_name = generateApplicationContainerName($application, $pull_request_id);
// ray('Stopping container: ' . $container_name);
instant_remote_process(["docker rm -f $container_name"], $application->destination->server); instant_remote_process(["docker rm -f $container_name"], $application->destination->server);
$return_payloads->push([ $return_payloads->push([
'application' => $application->name, 'application' => $application->name,

View File

@@ -19,6 +19,7 @@ use App\Notifications\Application\DeploymentFailed;
use App\Notifications\Application\DeploymentSuccess; use App\Notifications\Application\DeploymentSuccess;
use App\Traits\ExecuteRemoteCommand; use App\Traits\ExecuteRemoteCommand;
use Carbon\Carbon; use Carbon\Carbon;
use Exception;
use Illuminate\Bus\Queueable; use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldBeEncrypted; use Illuminate\Contracts\Queue\ShouldBeEncrypted;
use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Contracts\Queue\ShouldQueue;
@@ -1207,7 +1208,6 @@ class ApplicationDeploymentJob implements ShouldBeEncrypted, ShouldQueue
if ($this->application->custom_healthcheck_found) { if ($this->application->custom_healthcheck_found) {
$this->application_deployment_queue->addLogEntry('Custom healthcheck found, skipping default healthcheck.'); $this->application_deployment_queue->addLogEntry('Custom healthcheck found, skipping default healthcheck.');
} }
// ray('New container name: ', $this->container_name);
if ($this->container_name) { if ($this->container_name) {
$counter = 1; $counter = 1;
$this->application_deployment_queue->addLogEntry('Waiting for healthcheck to pass on the new container.'); $this->application_deployment_queue->addLogEntry('Waiting for healthcheck to pass on the new container.');
@@ -1410,7 +1410,6 @@ class ApplicationDeploymentJob implements ShouldBeEncrypted, ShouldQueue
continue; continue;
} }
// ray('Deploying to additional destination: ', $server->name);
$deployment_uuid = new Cuid2; $deployment_uuid = new Cuid2;
queue_application_deployment( queue_application_deployment(
deployment_uuid: $deployment_uuid, deployment_uuid: $deployment_uuid,
@@ -2023,6 +2022,8 @@ LABEL coolify.deploymentId={$this->deployment_uuid}
COPY . . COPY . .
RUN rm -f /usr/share/nginx/html/nginx.conf RUN rm -f /usr/share/nginx/html/nginx.conf
RUN rm -f /usr/share/nginx/html/Dockerfile 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"); COPY ./nginx.conf /etc/nginx/conf.d/default.conf");
if (str($this->application->custom_nginx_configuration)->isNotEmpty()) { if (str($this->application->custom_nginx_configuration)->isNotEmpty()) {
$nginx_config = base64_encode($this->application->custom_nginx_configuration); $nginx_config = base64_encode($this->application->custom_nginx_configuration);

View File

@@ -73,19 +73,21 @@ class StripeProcessJob implements ShouldQueue
} }
$subscription = Subscription::where('team_id', $teamId)->first(); $subscription = Subscription::where('team_id', $teamId)->first();
if ($subscription) { if ($subscription) {
send_internal_notification('Old subscription activated for team: '.$teamId); // send_internal_notification('Old subscription activated for team: '.$teamId);
$subscription->update([ $subscription->update([
'stripe_subscription_id' => $subscriptionId, 'stripe_subscription_id' => $subscriptionId,
'stripe_customer_id' => $customerId, 'stripe_customer_id' => $customerId,
'stripe_invoice_paid' => true, 'stripe_invoice_paid' => true,
'stripe_past_due' => false,
]); ]);
} else { } else {
send_internal_notification('New subscription for team: '.$teamId); // send_internal_notification('New subscription for team: '.$teamId);
Subscription::create([ Subscription::create([
'team_id' => $teamId, 'team_id' => $teamId,
'stripe_subscription_id' => $subscriptionId, 'stripe_subscription_id' => $subscriptionId,
'stripe_customer_id' => $customerId, 'stripe_customer_id' => $customerId,
'stripe_invoice_paid' => true, 'stripe_invoice_paid' => true,
'stripe_past_due' => false,
]); ]);
} }
break; break;
@@ -100,6 +102,7 @@ class StripeProcessJob implements ShouldQueue
if ($subscription) { if ($subscription) {
$subscription->update([ $subscription->update([
'stripe_invoice_paid' => true, 'stripe_invoice_paid' => true,
'stripe_past_due' => false,
]); ]);
} else { } else {
throw new \RuntimeException("No subscription found for customer: {$customerId}"); throw new \RuntimeException("No subscription found for customer: {$customerId}");
@@ -119,9 +122,7 @@ class StripeProcessJob implements ShouldQueue
} }
if (! $subscription->stripe_invoice_paid) { if (! $subscription->stripe_invoice_paid) {
SubscriptionInvoiceFailedJob::dispatch($team); SubscriptionInvoiceFailedJob::dispatch($team);
send_internal_notification('Invoice payment failed: '.$customerId); // send_internal_notification('Invoice payment failed: '.$customerId);
} else {
send_internal_notification('Invoice payment failed but already paid: '.$customerId);
} }
break; break;
case 'payment_intent.payment_failed': case 'payment_intent.payment_failed':
@@ -136,7 +137,7 @@ class StripeProcessJob implements ShouldQueue
return; return;
} }
send_internal_notification('Subscription payment failed for customer: '.$customerId); // send_internal_notification('Subscription payment failed for customer: '.$customerId);
break; break;
case 'customer.subscription.created': case 'customer.subscription.created':
$customerId = data_get($data, 'customer'); $customerId = data_get($data, 'customer');
@@ -158,7 +159,7 @@ class StripeProcessJob implements ShouldQueue
} }
$subscription = Subscription::where('team_id', $teamId)->first(); $subscription = Subscription::where('team_id', $teamId)->first();
if ($subscription) { if ($subscription) {
send_internal_notification("Subscription already exists for team: {$teamId}"); // send_internal_notification("Subscription already exists for team: {$teamId}");
throw new \RuntimeException("Subscription already exists for team: {$teamId}"); throw new \RuntimeException("Subscription already exists for team: {$teamId}");
} else { } else {
Subscription::create([ Subscription::create([
@@ -182,7 +183,7 @@ class StripeProcessJob implements ShouldQueue
$subscription = Subscription::where('stripe_customer_id', $customerId)->first(); $subscription = Subscription::where('stripe_customer_id', $customerId)->first();
if (! $subscription) { if (! $subscription) {
if ($status === 'incomplete_expired') { if ($status === 'incomplete_expired') {
send_internal_notification('Subscription incomplete expired'); // send_internal_notification('Subscription incomplete expired');
throw new \RuntimeException('Subscription incomplete expired'); throw new \RuntimeException('Subscription incomplete expired');
} }
if ($teamId) { if ($teamId) {
@@ -224,9 +225,33 @@ class StripeProcessJob implements ShouldQueue
]); ]);
} }
} }
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 ($status === 'active') {
if ($subscription->stripe_subscription_id === $subscriptionId) { if ($subscription->stripe_subscription_id === $subscriptionId) {
$subscription->update([ $subscription->update([
'stripe_past_due' => false,
'stripe_invoice_paid' => true, 'stripe_invoice_paid' => true,
]); ]);
} }

View File

@@ -35,10 +35,18 @@ class Docker extends Component
$this->network = new Cuid2; $this->network = new Cuid2;
$this->servers = Server::isUsable()->get(); $this->servers = Server::isUsable()->get();
if ($server_id) { if ($server_id) {
$this->selectedServer = $this->servers->find($server_id) ?: $this->servers->first(); $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; $this->serverId = $this->selectedServer->id;
} else { } else {
$this->selectedServer = $this->servers->first(); $foundServer = $this->servers->first();
if (! $foundServer) {
throw new \Exception('Server not found.');
}
$this->selectedServer = $foundServer;
$this->serverId = $this->selectedServer->id; $this->serverId = $this->selectedServer->id;
} }
$this->generateName(); $this->generateName();

View File

@@ -36,7 +36,7 @@ class Help extends Component
$type = set_transanctional_email_settings($settings); $type = set_transanctional_email_settings($settings);
// Sending feedback through Cloud API // Sending feedback through Cloud API
if ($type === false) { if (blank($type)) {
$url = 'https://app.coolify.io/api/feedback'; $url = 'https://app.coolify.io/api/feedback';
Http::post($url, [ Http::post($url, [
'content' => 'User: `'.auth()->user()?->email.'` with subject: `'.$this->subject.'` has the following problem: `'.$this->description.'`', 'content' => 'User: `'.auth()->user()?->email.'` with subject: `'.$this->subject.'` has the following problem: `'.$this->description.'`',

View File

@@ -2,7 +2,7 @@
namespace App\Livewire; namespace App\Livewire;
//use Livewire\Component; // use Livewire\Component;
use Illuminate\View\Component; use Illuminate\View\Component;
use Visus\Cuid2\Cuid2; use Visus\Cuid2\Cuid2;

View File

@@ -43,8 +43,10 @@ class Heading extends Component
public function check_status($showNotification = false) public function check_status($showNotification = false)
{ {
GetContainersStatus::run($this->database->destination->server); if ($this->database->destination->server->isFunctional()) {
$this->database->refresh(); GetContainersStatus::dispatch($this->database->destination->server);
}
if ($showNotification) { if ($showNotification) {
$this->dispatch('success', 'Database status updated.'); $this->dispatch('success', 'Database status updated.');
} }

View File

@@ -52,12 +52,6 @@ class DockerCompose extends Component
'dockerComposeRaw' => 'required', 'dockerComposeRaw' => 'required',
]); ]);
$this->dockerComposeRaw = Yaml::dump(Yaml::parse($this->dockerComposeRaw), 10, 2, Yaml::DUMP_MULTI_LINE_LITERAL_BLOCK); $this->dockerComposeRaw = Yaml::dump(Yaml::parse($this->dockerComposeRaw), 10, 2, Yaml::DUMP_MULTI_LINE_LITERAL_BLOCK);
$isValid = validateComposeFile($this->dockerComposeRaw, $server_id);
if ($isValid !== 'OK') {
return $this->dispatch('error', "Invalid docker-compose file.\n$isValid");
}
$project = Project::where('uuid', $this->parameters['project_uuid'])->first(); $project = Project::where('uuid', $this->parameters['project_uuid'])->first();
$environment = $project->load(['environments'])->environments->where('uuid', $this->parameters['environment_uuid'])->first(); $environment = $project->load(['environments'])->environments->where('uuid', $this->parameters['environment_uuid'])->first();

View File

@@ -92,7 +92,9 @@ class Configuration extends Component
public function check_status() public function check_status()
{ {
try { try {
GetContainersStatus::run($this->service->server); if ($this->service->server->isFunctional()) {
GetContainersStatus::dispatch($this->service->server);
}
$this->service->applications->each(function ($application) { $this->service->applications->each(function ($application) {
$application->refresh(); $application->refresh();
}); });

View File

@@ -31,12 +31,22 @@ class EditCompose extends Component
public function refreshEnvs() public function refreshEnvs()
{ {
$this->service = Service::find($this->serviceId); $this->service = Service::ownedByCurrentTeam()->find($this->serviceId);
} }
public function mount() public function mount()
{ {
$this->service = Service::find($this->serviceId); $this->service = Service::ownedByCurrentTeam()->find($this->serviceId);
}
public function validateCompose()
{
$isValid = validateComposeFile($this->service->docker_compose_raw, $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() public function saveEditedCompose()

View File

@@ -43,12 +43,11 @@ class EditDomain extends Component
updateCompose($this->application); updateCompose($this->application);
if (str($this->application->fqdn)->contains(',')) { 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.<br><br>Only use multiple domains if you know what you are doing.'); $this->dispatch('warning', 'Some services do not support multiple domains, which can lead to problems and is NOT RECOMMENDED.<br><br>Only use multiple domains if you know what you are doing.');
} else {
! $warning && $this->dispatch('success', 'Service saved.');
} }
$this->application->service->parse(); $this->application->service->parse();
$this->dispatch('refresh'); $this->dispatch('refresh');
$this->dispatch('configurationChanged'); $this->dispatch('configurationChanged');
$this->dispatch('refreshStatus');
} catch (\Throwable $e) { } catch (\Throwable $e) {
$originalFqdn = $this->application->getOriginal('fqdn'); $originalFqdn = $this->application->getOriginal('fqdn');
if ($originalFqdn !== $this->application->fqdn) { if ($originalFqdn !== $this->application->fqdn) {

View File

@@ -63,7 +63,7 @@ class StackForm extends Component
public function saveCompose($raw) public function saveCompose($raw)
{ {
$this->service->docker_compose_raw = $raw; $this->service->docker_compose_raw = $raw;
$this->submit(notify: false); $this->submit(notify: true);
} }
public function instantSave() public function instantSave()
@@ -76,10 +76,6 @@ class StackForm extends Component
{ {
try { try {
$this->validate(); $this->validate();
$isValid = validateComposeFile($this->service->docker_compose_raw, $this->service->server->id);
if ($isValid !== 'OK') {
throw new \Exception("Invalid docker-compose file.\n$isValid");
}
$this->service->save(); $this->service->save();
$this->service->saveExtraFields($this->fields); $this->service->saveExtraFields($this->fields);
$this->service->parse(); $this->service->parse();

View File

@@ -2,15 +2,22 @@
namespace App\Livewire\Project\Shared\ScheduledTask; namespace App\Livewire\Project\Shared\ScheduledTask;
use App\Models\ScheduledTask;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use Livewire\Attributes\Locked;
use Livewire\Component; use Livewire\Component;
class Add extends Component class Add extends Component
{ {
public $parameters; public $parameters;
#[Locked]
public string $id;
#[Locked]
public string $type; public string $type;
#[Locked]
public Collection $containerNames; public Collection $containerNames;
public string $name; public string $name;
@@ -21,8 +28,6 @@ class Add extends Component
public ?string $container = ''; public ?string $container = '';
protected $listeners = ['clearScheduledTask' => 'clear'];
protected $rules = [ protected $rules = [
'name' => 'required|string', 'name' => 'required|string',
'command' => 'required|string', 'command' => 'required|string',
@@ -60,18 +65,42 @@ class Add extends Component
$this->container = $this->subServiceName; $this->container = $this->subServiceName;
} }
} }
$this->dispatch('saveScheduledTask', [ $this->saveScheduledTask();
'name' => $this->name,
'command' => $this->command,
'frequency' => $this->frequency,
'container' => $this->container,
]);
$this->clear(); $this->clear();
} catch (\Exception $e) { } catch (\Exception $e) {
return handleError($e, $this); 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->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() public function clear()
{ {
$this->name = ''; $this->name = '';

View File

@@ -4,20 +4,22 @@ namespace App\Livewire\Project\Shared\ScheduledTask;
use App\Models\ScheduledTask; use App\Models\ScheduledTask;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use Livewire\Attributes\Locked;
use Livewire\Attributes\On;
use Livewire\Component; use Livewire\Component;
class All extends Component class All extends Component
{ {
#[Locked]
public $resource; public $resource;
#[Locked]
public array $parameters;
public Collection $containerNames; public Collection $containerNames;
public ?string $variables = null; public ?string $variables = null;
public array $parameters;
protected $listeners = ['refreshTasks', 'saveScheduledTask' => 'submit'];
public function mount() public function mount()
{ {
$this->parameters = get_route_parameters(); $this->parameters = get_route_parameters();
@@ -35,37 +37,10 @@ class All extends Component
} }
} }
#[On('refreshTasks')]
public function refreshTasks() public function refreshTasks()
{ {
$this->resource->refresh(); $this->resource->refresh();
} }
public function submit($data)
{
try {
$task = new ScheduledTask;
$task->name = $data['name'];
$task->command = $data['command'];
$task->frequency = $data['frequency'];
$task->container = $data['container'];
$task->team_id = currentTeam()->id;
switch ($this->resource->type()) {
case 'application':
$task->application_id = $this->resource->id;
break;
case 'standalone-postgresql':
$task->standalone_postgresql_id = $this->resource->id;
break;
case 'service':
$task->service_id = $this->resource->id;
break;
}
$task->save();
$this->refreshTasks();
$this->dispatch('success', 'Scheduled task added.');
} catch (\Throwable $e) {
return handleError($e, $this);
}
}
} }

View File

@@ -133,9 +133,9 @@ class Show extends Component
$this->task->delete(); $this->task->delete();
if ($this->type === 'application') { if ($this->type === 'application') {
return redirect()->route('project.application.configuration', $this->parameters, $this->task->name); return redirect()->route('project.application.scheduled-tasks.show', $this->parameters);
} else { } else {
return redirect()->route('project.service.configuration', $this->parameters, $this->task->name); return redirect()->route('project.service.scheduled-tasks.show', $this->parameters);
} }
} catch (\Exception $e) { } catch (\Exception $e) {
return handleError($e); return handleError($e);

View File

@@ -29,8 +29,6 @@ class Webhooks extends Component
public function mount() public function mount()
{ {
// ray()->clearAll();
// ray()->showQueries();
$this->deploywebhook = generateDeployWebhook($this->resource); $this->deploywebhook = generateDeployWebhook($this->resource);
$this->githubManualWebhookSecret = data_get($this->resource, 'manual_webhook_secret_github'); $this->githubManualWebhookSecret = data_get($this->resource, 'manual_webhook_secret_github');

View File

@@ -105,7 +105,6 @@ class Deploy extends Component
$startTime = Carbon::now()->getTimestamp(); $startTime = Carbon::now()->getTimestamp();
while ($process->running()) { while ($process->running()) {
ray('running');
if (Carbon::now()->getTimestamp() - $startTime >= $timeout) { if (Carbon::now()->getTimestamp() - $startTime >= $timeout) {
$this->forceStopContainer($containerName); $this->forceStopContainer($containerName);
break; break;

View File

@@ -7,6 +7,7 @@ use App\Actions\Server\StopSentinel;
use App\Events\ServerReachabilityChanged; use App\Events\ServerReachabilityChanged;
use App\Models\Server; use App\Models\Server;
use Livewire\Attributes\Computed; use Livewire\Attributes\Computed;
use Livewire\Attributes\Locked;
use Livewire\Attributes\Validate; use Livewire\Attributes\Validate;
use Livewire\Component; use Livewire\Component;
@@ -50,6 +51,9 @@ class Show extends Component
#[Validate(['required'])] #[Validate(['required'])]
public bool $isBuildServer; public bool $isBuildServer;
#[Locked]
public bool $isBuildServerLocked = false;
#[Validate(['required'])] #[Validate(['required'])]
public bool $isMetricsEnabled; public bool $isMetricsEnabled;
@@ -95,6 +99,9 @@ class Show extends Component
try { try {
$this->server = Server::ownedByCurrentTeam()->whereUuid($server_uuid)->firstOrFail(); $this->server = Server::ownedByCurrentTeam()->whereUuid($server_uuid)->firstOrFail();
$this->syncData(); $this->syncData();
if (! $this->server->isEmpty()) {
$this->isBuildServerLocked = true;
}
} catch (\Throwable $e) { } catch (\Throwable $e) {
return handleError($e, $this); return handleError($e, $this);
} }

View File

@@ -36,7 +36,7 @@ class SettingsEmail extends Component
public ?int $smtpPort = null; public ?int $smtpPort = null;
#[Validate(['nullable', 'string', 'in:starttls,tls,none'])] #[Validate(['nullable', 'string', 'in:starttls,tls,none'])]
public ?string $smtpEncryption = null; public ?string $smtpEncryption = 'starttls';
#[Validate(['nullable', 'string'])] #[Validate(['nullable', 'string'])]
public ?string $smtpUsername = null; public ?string $smtpUsername = null;

View File

@@ -37,6 +37,8 @@ class Change extends Component
public $applications; public $applications;
public $privateKeys;
protected $rules = [ protected $rules = [
'github_app.name' => 'required|string', 'github_app.name' => 'required|string',
'github_app.organization' => 'nullable|string', 'github_app.organization' => 'nullable|string',
@@ -54,6 +56,7 @@ class Change extends Component
'github_app.metadata' => 'nullable|string', 'github_app.metadata' => 'nullable|string',
'github_app.pull_requests' => 'nullable|string', 'github_app.pull_requests' => 'nullable|string',
'github_app.administration' => 'nullable|string', 'github_app.administration' => 'nullable|string',
'github_app.private_key_id' => 'required|int',
]; ];
public function boot() public function boot()
@@ -65,9 +68,13 @@ class Change extends Component
public function checkPermissions() public function checkPermissions()
{ {
GithubAppPermissionJob::dispatchSync($this->github_app); try {
$this->github_app->refresh()->makeVisible('client_secret')->makeVisible('webhook_secret'); GithubAppPermissionJob::dispatchSync($this->github_app);
$this->dispatch('success', 'Github App permissions updated.'); $this->github_app->refresh()->makeVisible('client_secret')->makeVisible('webhook_secret');
$this->dispatch('success', 'Github App permissions updated.');
} catch (\Throwable $e) {
return handleError($e, $this);
}
} }
// public function check() // public function check()
@@ -101,7 +108,6 @@ class Change extends Component
// ]); // ]);
// } // }
// ray($runners_by_repository);
// } // }
public function mount() public function mount()
@@ -110,6 +116,7 @@ class Change extends Component
$github_app_uuid = request()->github_app_uuid; $github_app_uuid = request()->github_app_uuid;
$this->github_app = GithubApp::ownedByCurrentTeam()->whereUuid($github_app_uuid)->firstOrFail(); $this->github_app = GithubApp::ownedByCurrentTeam()->whereUuid($github_app_uuid)->firstOrFail();
$this->github_app->makeVisible(['client_secret', 'webhook_secret']); $this->github_app->makeVisible(['client_secret', 'webhook_secret']);
$this->privateKeys = PrivateKey::ownedByCurrentTeam()->get();
$this->applications = $this->github_app->applications; $this->applications = $this->github_app->applications;
$settings = instanceSettings(); $settings = instanceSettings();
@@ -244,6 +251,7 @@ class Change extends Component
'github_app.client_secret' => 'required|string', 'github_app.client_secret' => 'required|string',
'github_app.webhook_secret' => 'required|string', 'github_app.webhook_secret' => 'required|string',
'github_app.is_system_wide' => 'required|bool', 'github_app.is_system_wide' => 'required|bool',
'github_app.private_key_id' => 'required|int',
]); ]);
$this->github_app->save(); $this->github_app->save();
$this->dispatch('success', 'Github App updated.'); $this->dispatch('success', 'Github App updated.');
@@ -252,6 +260,15 @@ class Change extends Component
} }
} }
public function createGithubAppManually()
{
$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();
$this->dispatch('success', 'Github App updated.');
}
public function instantSave() public function instantSave()
{ {
try { try {

View File

@@ -17,6 +17,7 @@ use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Support\Carbon; use Illuminate\Support\Carbon;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Storage; use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Stringable; use Illuminate\Support\Stringable;
use OpenApi\Attributes as OA; use OpenApi\Attributes as OA;
@@ -24,6 +25,7 @@ use Spatie\SchemalessAttributes\Casts\SchemalessAttributes;
use Spatie\SchemalessAttributes\SchemalessAttributesTrait; use Spatie\SchemalessAttributes\SchemalessAttributesTrait;
use Spatie\Url\Url; use Spatie\Url\Url;
use Symfony\Component\Yaml\Yaml; use Symfony\Component\Yaml\Yaml;
use Visus\Cuid2\Cuid2;
#[OA\Schema( #[OA\Schema(
description: 'Server model', description: 'Server model',
@@ -101,11 +103,13 @@ class Server extends BaseModel
'server_id' => $server->id, 'server_id' => $server->id,
]); ]);
} else { } else {
StandaloneDocker::create([ $standaloneDocker = new StandaloneDocker([
'name' => 'coolify', 'name' => 'coolify',
'uuid' => (string) new Cuid2,
'network' => 'coolify', 'network' => 'coolify',
'server_id' => $server->id, 'server_id' => $server->id,
]); ]);
$standaloneDocker->saveQuietly();
} }
} }
if (! isset($server->proxy->redirect_enabled)) { if (! isset($server->proxy->redirect_enabled)) {
@@ -437,10 +441,6 @@ class Server extends BaseModel
"mkdir -p $dynamic_config_path", "mkdir -p $dynamic_config_path",
"echo '$base64' | base64 -d | tee $file > /dev/null", "echo '$base64' | base64 -d | tee $file > /dev/null",
], $this); ], $this);
if (config('app.env') === 'local') {
// ray($yaml);
}
} }
} elseif ($this->proxyType() === 'CADDY') { } elseif ($this->proxyType() === 'CADDY') {
$file = "$dynamic_config_path/coolify.caddy"; $file = "$dynamic_config_path/coolify.caddy";
@@ -709,22 +709,6 @@ $schema://$host {
]; ];
} }
public function getContainersWithSentinel(): Collection
{
$sentinel_found = instant_remote_process(['docker inspect coolify-sentinel'], $this, false);
$sentinel_found = json_decode($sentinel_found, true);
$status = data_get($sentinel_found, '0.State.Status', 'exited');
if ($status === 'running') {
$containers = instant_remote_process(['docker exec coolify-sentinel sh -c "curl http://127.0.0.1:8888/api/containers"'], $this, false);
if (is_null($containers)) {
return collect([]);
}
$containers = data_get(json_decode($containers, true), 'containers', []);
return collect($containers);
}
}
public function loadAllContainers(): Collection public function loadAllContainers(): Collection
{ {
if ($this->isFunctional()) { if ($this->isFunctional()) {
@@ -970,10 +954,8 @@ $schema://$host {
} }
}); });
if ($supported->count() === 1) { if ($supported->count() === 1) {
// ray('supported');
return str($supported->first()); return str($supported->first());
} else { } else {
// ray('not supported');
return false; return false;
} }
} }
@@ -1042,7 +1024,7 @@ $schema://$host {
$unreachableNotificationSent = (bool) $this->unreachable_notification_sent; $unreachableNotificationSent = (bool) $this->unreachable_notification_sent;
$isReachable = (bool) $this->settings->is_reachable; $isReachable = (bool) $this->settings->is_reachable;
\Log::debug('Server reachability check', [ Log::debug('Server reachability check', [
'server_id' => $this->id, 'server_id' => $this->id,
'is_reachable' => $isReachable, 'is_reachable' => $isReachable,
'notification_sent' => $unreachableNotificationSent, 'notification_sent' => $unreachableNotificationSent,
@@ -1054,7 +1036,7 @@ $schema://$host {
$this->save(); $this->save();
if ($unreachableNotificationSent === true) { if ($unreachableNotificationSent === true) {
\Log::debug('Server is now reachable, sending notification', [ Log::debug('Server is now reachable, sending notification', [
'server_id' => $this->id, 'server_id' => $this->id,
]); ]);
$this->sendReachableNotification(); $this->sendReachableNotification();
@@ -1064,7 +1046,7 @@ $schema://$host {
} }
$this->increment('unreachable_count'); $this->increment('unreachable_count');
\Log::debug('Incremented unreachable count', [ Log::debug('Incremented unreachable count', [
'server_id' => $this->id, 'server_id' => $this->id,
'new_count' => $this->unreachable_count, 'new_count' => $this->unreachable_count,
]); ]);
@@ -1072,7 +1054,7 @@ $schema://$host {
if ($this->unreachable_count === 1) { if ($this->unreachable_count === 1) {
$this->settings->is_reachable = true; $this->settings->is_reachable = true;
$this->settings->save(); $this->settings->save();
\Log::debug('First unreachable attempt, marking as reachable', [ Log::debug('First unreachable attempt, marking as reachable', [
'server_id' => $this->id, 'server_id' => $this->id,
]); ]);
@@ -1083,7 +1065,7 @@ $schema://$host {
$failedChecks = 0; $failedChecks = 0;
for ($i = 0; $i < 3; $i++) { for ($i = 0; $i < 3; $i++) {
$status = $this->serverStatus(); $status = $this->serverStatus();
\Log::debug('Additional reachability check', [ Log::debug('Additional reachability check', [
'server_id' => $this->id, 'server_id' => $this->id,
'attempt' => $i + 1, 'attempt' => $i + 1,
'status' => $status, 'status' => $status,
@@ -1095,7 +1077,7 @@ $schema://$host {
} }
if ($failedChecks === 3 && ! $unreachableNotificationSent) { if ($failedChecks === 3 && ! $unreachableNotificationSent) {
\Log::debug('Server confirmed unreachable after 3 attempts, sending notification', [ Log::debug('Server confirmed unreachable after 3 attempts, sending notification', [
'server_id' => $this->id, 'server_id' => $this->id,
]); ]);
$this->sendUnreachableNotification(); $this->sendUnreachableNotification();
@@ -1341,4 +1323,11 @@ $schema://$host {
throw new \Exception('Invalid proxy type.'); throw new \Exception('Invalid proxy type.');
} }
} }
public function isEmpty()
{
return $this->applications()->count() == 0 &&
$this->databases()->count() == 0 &&
$this->services()->count() == 0;
}
} }

View File

@@ -78,11 +78,15 @@ class ServiceDatabase extends BaseModel
public function databaseType() public function databaseType()
{ {
$image = str($this->image)->before(':'); $image = str($this->image)->before(':');
if ($image->contains('postgres') || $image->contains('postgis')) { if ($image->contains('supabase/postgres')) {
$image = 'postgresql'; $finalImage = 'supabase/postgres';
} elseif ($image->contains('postgres') || $image->contains('postgis')) {
$finalImage = 'postgresql';
} else {
$finalImage = $image;
} }
return "standalone-$image"; return "standalone-$finalImage";
} }
public function getServiceDatabaseUrl() public function getServiceDatabaseUrl()

View File

@@ -93,6 +93,15 @@ class Team extends Model implements SendsDiscord, SendsEmail, SendsPushover, Sen
return $servers >= $serverLimit; return $servers >= $serverLimit;
} }
public function subscriptionPastOverDue()
{
if (isCloud()) {
return $this->subscription?->stripe_past_due;
}
return false;
}
public function serverOverflow() public function serverOverflow()
{ {
if ($this->serverLimit() < $this->servers->count()) { if ($this->serverLimit() < $this->servers->count()) {
@@ -185,6 +194,7 @@ class Team extends Model implements SendsDiscord, SendsEmail, SendsPushover, Sen
'stripe_cancel_at_period_end' => false, 'stripe_cancel_at_period_end' => false,
'stripe_invoice_paid' => false, 'stripe_invoice_paid' => false,
'stripe_trial_already_ended' => false, 'stripe_trial_already_ended' => false,
'stripe_past_due' => false,
]); ]);
foreach ($this->servers as $server) { foreach ($this->servers as $server) {
$server->settings()->update([ $server->settings()->update([

View File

@@ -44,7 +44,7 @@ class DeploymentSuccess extends CustomEmailNotification
if (str($this->fqdn)->explode(',')->count() > 1) { if (str($this->fqdn)->explode(',')->count() > 1) {
$this->fqdn = str($this->fqdn)->explode(',')->first(); $this->fqdn = str($this->fqdn)->explode(',')->first();
} }
$this->deployment_url = base_url()."/project/{$this->project_uuid}/environments/{$this->environment_uuid}/application/{$this->application->uuid}/deployment/{$this->deployment_uuid}"; $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 public function via(object $notifiable): array

View File

@@ -34,7 +34,7 @@ class StatusChanged extends CustomEmailNotification
if (str($this->fqdn)->explode(',')->count() > 1) { if (str($this->fqdn)->explode(',')->count() > 1) {
$this->fqdn = str($this->fqdn)->explode(',')->first(); $this->fqdn = str($this->fqdn)->explode(',')->first();
} }
$this->resource_url = base_url()."/project/{$this->project_uuid}/environments/{$this->environment_uuid}/application/{$this->resource->uuid}"; $this->resource_url = base_url()."/project/{$this->project_uuid}/environment/{$this->environment_uuid}/application/{$this->resource->uuid}";
} }
public function via(object $notifiable): array public function via(object $notifiable): array

View File

@@ -50,11 +50,9 @@ class EmailChannel
if ($emailSettings->use_instance_email_settings) { if ($emailSettings->use_instance_email_settings) {
$type = set_transanctional_email_settings(); $type = set_transanctional_email_settings();
if (! $type) { if (blank($type)) {
throw new Exception('No email settings found.'); throw new Exception('No email settings found.');
} }
config()->set('mail.default', $type);
return; return;
} }

View File

@@ -35,7 +35,7 @@ class TransactionalEmailChannel
private function bootConfigs(): void private function bootConfigs(): void
{ {
$type = set_transanctional_email_settings(); $type = set_transanctional_email_settings();
if (! $type) { if (blank($type)) {
throw new Exception('No email settings found.'); throw new Exception('No email settings found.');
} }
} }

View File

@@ -40,7 +40,7 @@ class PushoverMessage
if ($buttonUrl && str_contains($buttonUrl, 'http://localhost')) { if ($buttonUrl && str_contains($buttonUrl, 'http://localhost')) {
$buttonUrl = str_replace('http://localhost', config('app.url'), $buttonUrl); $buttonUrl = str_replace('http://localhost', config('app.url'), $buttonUrl);
} }
$payload['message'] .= "&nbsp;<a href='" . $buttonUrl . "'>" . $text . '</a>'; $payload['message'] .= "&nbsp;<a href='".$buttonUrl."'>".$text.'</a>';
} }
Log::info('Pushover message', $payload); Log::info('Pushover message', $payload);

View File

@@ -3,6 +3,7 @@
namespace App\Notifications\TransactionalEmails; namespace App\Notifications\TransactionalEmails;
use App\Models\InstanceSettings; use App\Models\InstanceSettings;
use Exception;
use Illuminate\Notifications\Messages\MailMessage; use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification; use Illuminate\Notifications\Notification;
@@ -35,8 +36,8 @@ class ResetPassword extends Notification
public function via($notifiable) public function via($notifiable)
{ {
$type = set_transanctional_email_settings(); $type = set_transanctional_email_settings();
if (! $type) { if (blank($type)) {
throw new \Exception('No email settings found.'); throw new Exception('No email settings found.');
} }
return ['mail']; return ['mail'];

View File

@@ -11,6 +11,7 @@ use Illuminate\Foundation\Events\MaintenanceModeEnabled;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider; use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
use SocialiteProviders\Authentik\AuthentikExtendSocialite; use SocialiteProviders\Authentik\AuthentikExtendSocialite;
use SocialiteProviders\Azure\AzureExtendSocialite; use SocialiteProviders\Azure\AzureExtendSocialite;
use SocialiteProviders\Google\GoogleExtendSocialite;
use SocialiteProviders\Infomaniak\InfomaniakExtendSocialite; use SocialiteProviders\Infomaniak\InfomaniakExtendSocialite;
use SocialiteProviders\Manager\SocialiteWasCalled; use SocialiteProviders\Manager\SocialiteWasCalled;
@@ -26,6 +27,7 @@ class EventServiceProvider extends ServiceProvider
SocialiteWasCalled::class => [ SocialiteWasCalled::class => [
AzureExtendSocialite::class.'@handle', AzureExtendSocialite::class.'@handle',
AuthentikExtendSocialite::class.'@handle', AuthentikExtendSocialite::class.'@handle',
GoogleExtendSocialite::class.'@handle',
InfomaniakExtendSocialite::class.'@handle', InfomaniakExtendSocialite::class.'@handle',
], ],
ProxyStarted::class => [ ProxyStarted::class => [

View File

@@ -4,9 +4,9 @@ namespace App\Traits;
use App\Notifications\Channels\DiscordChannel; use App\Notifications\Channels\DiscordChannel;
use App\Notifications\Channels\EmailChannel; use App\Notifications\Channels\EmailChannel;
use App\Notifications\Channels\PushoverChannel;
use App\Notifications\Channels\SlackChannel; use App\Notifications\Channels\SlackChannel;
use App\Notifications\Channels\TelegramChannel; use App\Notifications\Channels\TelegramChannel;
use App\Notifications\Channels\PushoverChannel;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
trait HasNotificationSettings trait HasNotificationSettings

View File

@@ -91,8 +91,6 @@ function next_queuable(string $server_id, string $application_id): bool
$server = Server::find($server_id); $server = Server::find($server_id);
$concurrent_builds = $server->settings->concurrent_builds; $concurrent_builds = $server->settings->concurrent_builds;
// ray("serverId:{$server->id}", "concurrentBuilds:{$concurrent_builds}", "deployments:{$deployments->count()}", "sameApplicationDeployments:{$same_application_deployments->count()}")->green();
if ($deployments->count() > $concurrent_builds) { if ($deployments->count() > $concurrent_builds) {
return false; return false;
} }

View File

@@ -778,7 +778,6 @@ function convertDockerRunToCompose(?string $custom_docker_run_options = null)
} }
} }
} }
ray($payload);
$compose_options->put('deploy', [ $compose_options->put('deploy', [
'resources' => [ 'resources' => [
'reservations' => [ 'reservations' => [
@@ -829,26 +828,29 @@ function generateCustomDockerRunOptionsForDatabases($docker_run_options, $docker
function validateComposeFile(string $compose, int $server_id): string|Throwable function validateComposeFile(string $compose, int $server_id): string|Throwable
{ {
return 'OK'; $uuid = Str::random(18);
$server = Server::ownedByCurrentTeam()->find($server_id);
try { try {
$uuid = Str::random(10); if (! $server) {
$server = Server::findOrFail($server_id); throw new \Exception('Server not found');
}
$base64_compose = base64_encode($compose); $base64_compose = base64_encode($compose);
$output = instant_remote_process([ instant_remote_process([
"echo {$base64_compose} | base64 -d | tee /tmp/{$uuid}.yml > /dev/null", "echo {$base64_compose} | base64 -d | tee /tmp/{$uuid}.yml > /dev/null",
"docker compose -f /tmp/{$uuid}.yml config", "chmod 600 /tmp/{$uuid}.yml",
"docker compose -f /tmp/{$uuid}.yml config --no-interpolate --no-path-resolution -q",
"rm /tmp/{$uuid}.yml",
], $server); ], $server);
ray($output);
return 'OK'; return 'OK';
} catch (\Throwable $e) { } catch (\Throwable $e) {
ray($e);
return $e->getMessage(); return $e->getMessage();
} finally { } finally {
instant_remote_process([ if (filled($server)) {
"rm /tmp/{$uuid}.yml", instant_remote_process([
], $server); "rm /tmp/{$uuid}.yml",
], $server, throwError: false);
}
} }
} }

View File

@@ -28,7 +28,7 @@ function send_user_an_email(MailMessage $mail, string $email, ?string $cc = null
{ {
$settings = instanceSettings(); $settings = instanceSettings();
$type = set_transanctional_email_settings($settings); $type = set_transanctional_email_settings($settings);
if (! $type) { if (blank($type)) {
throw new Exception('No email settings found.'); throw new Exception('No email settings found.');
} }
if ($cc) { if ($cc) {
@@ -54,15 +54,19 @@ function send_user_an_email(MailMessage $mail, string $email, ?string $cc = null
} }
} }
function set_transanctional_email_settings(?InstanceSettings $settings = null): ?string // function set_transanctional_email_settings(?InstanceSettings $settings = null): ?string // returns null|resend|smtp and defaults to array based on mail.php config
{ {
if (! $settings) { if (! $settings) {
$settings = instanceSettings(); $settings = instanceSettings();
} }
config()->set('mail.from.address', data_get($settings, 'smtp_from_address')); if (! data_get($settings, 'smtp_enabled') && ! data_get($settings, 'resend_enabled')) {
config()->set('mail.from.name', data_get($settings, 'smtp_from_name')); return null;
}
if (data_get($settings, 'resend_enabled')) { if (data_get($settings, 'resend_enabled')) {
config()->set('mail.default', 'resend'); config()->set('mail.default', 'resend');
config()->set('mail.from.address', data_get($settings, 'smtp_from_address'));
config()->set('mail.from.name', data_get($settings, 'smtp_from_name'));
config()->set('resend.api_key', data_get($settings, 'resend_api_key')); config()->set('resend.api_key', data_get($settings, 'resend_api_key'));
return 'resend'; return 'resend';
@@ -76,6 +80,8 @@ function set_transanctional_email_settings(?InstanceSettings $settings = null):
}; };
if (data_get($settings, 'smtp_enabled')) { if (data_get($settings, 'smtp_enabled')) {
config()->set('mail.from.address', data_get($settings, 'smtp_from_address'));
config()->set('mail.from.name', data_get($settings, 'smtp_from_name'));
config()->set('mail.default', 'smtp'); config()->set('mail.default', 'smtp');
config()->set('mail.mailers.smtp', [ config()->set('mail.mailers.smtp', [
'transport' => 'smtp', 'transport' => 'smtp',
@@ -91,6 +97,4 @@ function set_transanctional_email_settings(?InstanceSettings $settings = null):
return 'smtp'; return 'smtp';
} }
return null;
} }

View File

@@ -748,6 +748,7 @@ function parseCommandFromMagicEnvVariable(Str|string $key): Stringable
{ {
$value = str($key); $value = str($key);
$count = substr_count($value->value(), '_'); $count = substr_count($value->value(), '_');
$command = null;
if ($count === 2) { if ($count === 2) {
if ($value->startsWith('SERVICE_FQDN') || $value->startsWith('SERVICE_URL')) { if ($value->startsWith('SERVICE_FQDN') || $value->startsWith('SERVICE_URL')) {
// SERVICE_FQDN_UMAMI // SERVICE_FQDN_UMAMI
@@ -800,7 +801,6 @@ function parseEnvVariable(Str|string $value)
} else { } else {
// SERVICE_BASE64_64_UMAMI // SERVICE_BASE64_64_UMAMI
$command = $value->after('SERVICE_')->beforeLast('_'); $command = $value->after('SERVICE_')->beforeLast('_');
ray($command);
} }
} }
} }
@@ -952,7 +952,6 @@ function validate_dns_entry(string $fqdn, Server $server)
$type = \PurplePixie\PhpDns\DNSTypes::NAME_A; $type = \PurplePixie\PhpDns\DNSTypes::NAME_A;
foreach ($dns_servers as $dns_server) { foreach ($dns_servers as $dns_server) {
try { try {
ray("Checking $host on $dns_server");
$query = new DNSQuery($dns_server); $query = new DNSQuery($dns_server);
$results = $query->query($host, $type); $results = $query->query($host, $type);
if ($results === false || $query->hasError()) { if ($results === false || $query->hasError()) {
@@ -961,13 +960,10 @@ function validate_dns_entry(string $fqdn, Server $server)
foreach ($results as $result) { foreach ($results as $result) {
if ($result->getType() == $type) { if ($result->getType() == $type) {
if (ip_match($result->getData(), $cloudflare_ips->toArray(), $match)) { if (ip_match($result->getData(), $cloudflare_ips->toArray(), $match)) {
ray("Found match in Cloudflare IPs: $match");
$found_matching_ip = true; $found_matching_ip = true;
break; break;
} }
if ($result->getData() === $ip) { if ($result->getData() === $ip) {
ray($host.' has IP address '.$result->getData());
ray($result->getString());
$found_matching_ip = true; $found_matching_ip = true;
break; break;
} }
@@ -977,7 +973,6 @@ function validate_dns_entry(string $fqdn, Server $server)
} catch (\Exception) { } catch (\Exception) {
} }
} }
ray("Found match: $found_matching_ip");
return $found_matching_ip; return $found_matching_ip;
} }
@@ -1331,7 +1326,6 @@ function parseServiceVolumes($serviceVolumes, $resource, $topLevelVolumes, $pull
$isDirectory = (bool) data_get($volume, 'isDirectory', null) || (bool) data_get($volume, 'is_directory', null); $isDirectory = (bool) data_get($volume, 'isDirectory', null) || (bool) data_get($volume, 'is_directory', null);
if ((is_null($isDirectory) || ! $isDirectory) && is_null($content)) { if ((is_null($isDirectory) || ! $isDirectory) && is_null($content)) {
// if isDirectory is not set (or false) & content is also not set, we assume it is a directory // if isDirectory is not set (or false) & content is also not set, we assume it is a directory
ray('setting isDirectory to true');
$isDirectory = true; $isDirectory = true;
} }
} }
@@ -1499,7 +1493,6 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
$serviceLabels->push("$removedLabelName=$removedLabel"); $serviceLabels->push("$removedLabelName=$removedLabel");
} }
} }
$containerName = "$serviceName-{$resource->uuid}"; $containerName = "$serviceName-{$resource->uuid}";
// Decide if the service is a database // Decide if the service is a database
@@ -1662,7 +1655,6 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
} }
if (is_null($isDirectory) && is_null($content)) { if (is_null($isDirectory) && is_null($content)) {
// if isDirectory is not set & content is also not set, we assume it is a directory // if isDirectory is not set & content is also not set, we assume it is a directory
ray('setting isDirectory to true');
$isDirectory = true; $isDirectory = true;
} }
} }
@@ -2529,9 +2521,6 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
} }
} }
} }
if ($collectedPorts->count() > 0) {
ray($collectedPorts->implode(','));
}
$definedNetworkExists = $topLevelNetworks->contains(function ($value, $_) use ($definedNetwork) { $definedNetworkExists = $topLevelNetworks->contains(function ($value, $_) use ($definedNetwork) {
return $value == $definedNetwork; return $value == $definedNetwork;
}); });
@@ -2956,7 +2945,6 @@ function newParser(Application|Service $resource, int $pull_request_id = 0, ?int
} }
$parsedServices = collect([]); $parsedServices = collect([]);
// ray()->clearAll();
$allMagicEnvironments = collect([]); $allMagicEnvironments = collect([]);
foreach ($services as $serviceName => $service) { foreach ($services as $serviceName => $service) {
@@ -3016,7 +3004,7 @@ function newParser(Application|Service $resource, int $pull_request_id = 0, ?int
$environment = $environment->merge($buildArgs); $environment = $environment->merge($buildArgs);
// convert environment variables to one format // convert environment variables to one format
$environment = convertComposeEnvironmentToArray($environment); $environment = convertToKeyValueCollection($environment);
// Add Coolify defined environments // Add Coolify defined environments
$allEnvironments = $resource->environment_variables()->get(['key', 'value']); $allEnvironments = $resource->environment_variables()->get(['key', 'value']);
@@ -3197,7 +3185,7 @@ function newParser(Application|Service $resource, int $pull_request_id = 0, ?int
$buildArgs = collect(data_get($service, 'build.args', [])); $buildArgs = collect(data_get($service, 'build.args', []));
$environment = $environment->merge($buildArgs); $environment = $environment->merge($buildArgs);
$environment = convertComposeEnvironmentToArray($environment); $environment = convertToKeyValueCollection($environment);
$coolifyEnvironments = collect([]); $coolifyEnvironments = collect([]);
$isDatabase = isDatabaseImage(data_get_str($service, 'image')); $isDatabase = isDatabaseImage(data_get_str($service, 'image'));
@@ -3934,7 +3922,7 @@ function add_coolify_default_environment_variables(StandaloneRedis|StandalonePos
} }
} }
function convertComposeEnvironmentToArray($environment) function convertToKeyValueCollection($environment)
{ {
$convertedServiceVariables = collect([]); $convertedServiceVariables = collect([]);
if (isAssociativeArray($environment)) { if (isAssociativeArray($environment)) {

View File

@@ -29,6 +29,18 @@ function get_socialite_provider(string $provider)
return Socialite::driver('authentik')->setConfig($authentik_config); return Socialite::driver('authentik')->setConfig($authentik_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 = [ $config = [
'client_id' => $oauth_setting->client_id, 'client_id' => $oauth_setting->client_id,
'client_secret' => $oauth_setting->client_secret, 'client_secret' => $oauth_setting->client_secret,
@@ -39,7 +51,6 @@ function get_socialite_provider(string $provider)
'bitbucket' => \Laravel\Socialite\Two\BitbucketProvider::class, 'bitbucket' => \Laravel\Socialite\Two\BitbucketProvider::class,
'github' => \Laravel\Socialite\Two\GithubProvider::class, 'github' => \Laravel\Socialite\Two\GithubProvider::class,
'gitlab' => \Laravel\Socialite\Two\GitlabProvider::class, 'gitlab' => \Laravel\Socialite\Two\GitlabProvider::class,
'google' => \Laravel\Socialite\Two\GoogleProvider::class,
'infomaniak' => \SocialiteProviders\Infomaniak\Provider::class, 'infomaniak' => \SocialiteProviders\Infomaniak\Provider::class,
]; ];

View File

@@ -40,6 +40,7 @@
"resend/resend-laravel": "^0.15.0", "resend/resend-laravel": "^0.15.0",
"sentry/sentry-laravel": "^4.6", "sentry/sentry-laravel": "^4.6",
"socialiteproviders/authentik": "^5.2", "socialiteproviders/authentik": "^5.2",
"socialiteproviders/google": "^4.1",
"socialiteproviders/infomaniak": "^4.0", "socialiteproviders/infomaniak": "^4.0",
"socialiteproviders/microsoft-azure": "^5.1", "socialiteproviders/microsoft-azure": "^5.1",
"spatie/laravel-activitylog": "^4.7.3", "spatie/laravel-activitylog": "^4.7.3",
@@ -125,4 +126,4 @@
"@php artisan key:generate --ansi" "@php artisan key:generate --ansi"
] ]
} }
} }

1558
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,5 @@
<?php <?php
/** /**
* @see https://github.com/pionl/laravel-chunk-upload * @see https://github.com/pionl/laravel-chunk-upload
*/ */

View File

@@ -2,9 +2,9 @@
return [ return [
'coolify' => [ 'coolify' => [
'version' => '4.0.0-beta.394', 'version' => '4.0.0-beta.399',
'helper_version' => '1.0.6', 'helper_version' => '1.0.7',
'realtime_version' => '1.0.5', 'realtime_version' => '1.0.6',
'self_hosted' => env('SELF_HOSTED', true), 'self_hosted' => env('SELF_HOSTED', true),
'autoupdate' => env('AUTOUPDATE'), 'autoupdate' => env('AUTOUPDATE'),
'base_config_path' => env('BASE_CONFIG_PATH', '/data/coolify'), 'base_config_path' => env('BASE_CONFIG_PATH', '/data/coolify'),

View File

@@ -38,7 +38,7 @@ return [
'pgsql' => [ 'pgsql' => [
'driver' => 'pgsql', 'driver' => 'pgsql',
'url' => env('DATABASE_URL'), 'url' => env('DATABASE_URL'),
'host' => env('DB_HOST', 'postgres'), 'host' => env('DB_HOST', 'coolify-db'),
'port' => env('DB_PORT', '5432'), 'port' => env('DB_PORT', '5432'),
'database' => env('DB_DATABASE', 'coolify'), 'database' => env('DB_DATABASE', 'coolify'),
'username' => env('DB_USERNAME', 'coolify'), 'username' => env('DB_USERNAME', 'coolify'),

View File

@@ -234,7 +234,7 @@ return [
], ],
'views' => [ 'views' => [
'timeline' => false, // Add the views to the timeline (Experimental) 'timeline' => false, // Add the views to the timeline (Experimental)
'data' => false, //true for all data, 'keys' for only names, false for no parameters. '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 '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 'exclude_paths' => [ // Add the paths which you don't want to appear in the views
'vendor/filament', // Exclude Filament components by default 'vendor/filament', // Exclude Filament components by default

View File

@@ -13,7 +13,7 @@ return [
| |
*/ */
'default' => env('MAIL_MAILER', null), 'default' => env('MAIL_MAILER', 'array'),
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------

View File

@@ -45,4 +45,12 @@ return [
'client_secret' => env('AUTHENTIK_CLIENT_SECRET'), 'client_secret' => env('AUTHENTIK_CLIENT_SECRET'),
'redirect' => env('AUTHENTIK_REDIRECT_URI'), 'redirect' => env('AUTHENTIK_REDIRECT_URI'),
], ],
'google' => [
'client_id' => env('GOOGLE_CLIENT_ID'),
'client_secret' => env('GOOGLE_CLIENT_SECRET'),
'redirect' => env('GOOGLE_REDIRECT_URI'),
'tenant' => env('GOOGLE_TENANT'),
],
]; ];

View File

@@ -0,0 +1,38 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('scheduled_task_executions', function (Blueprint $table) {
$table->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');
});
}
};

View File

@@ -0,0 +1,28 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('subscriptions', function (Blueprint $table) {
$table->boolean('stripe_past_due')->default(false);
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('subscriptions', function (Blueprint $table) {
$table->dropColumn('stripe_past_due');
});
}
};

View File

@@ -21,7 +21,7 @@ class GithubAppSeeder extends Seeder
'team_id' => 0, 'team_id' => 0,
]); ]);
GithubApp::create([ GithubApp::create([
'name' => 'coolify-laravel-development-public', 'name' => 'coolify-laravel-dev-public',
'uuid' => '69420', 'uuid' => '69420',
'organization' => 'coollabsio', 'organization' => 'coollabsio',
'api_url' => 'https://api.github.com', 'api_url' => 'https://api.github.com',

View File

@@ -61,7 +61,7 @@ services:
retries: 10 retries: 10
timeout: 2s timeout: 2s
soketi: soketi:
image: 'ghcr.io/coollabsio/coolify-realtime:1.0.5' image: 'ghcr.io/coollabsio/coolify-realtime:1.0.6'
ports: ports:
- "${SOKETI_PORT:-6001}:6001" - "${SOKETI_PORT:-6001}:6001"
- "6002:6002" - "6002:6002"

View File

@@ -103,7 +103,7 @@ services:
retries: 10 retries: 10
timeout: 2s timeout: 2s
soketi: soketi:
image: 'ghcr.io/coollabsio/coolify-realtime:1.0.4' image: 'ghcr.io/coollabsio/coolify-realtime:1.0.6'
pull_policy: always pull_policy: always
container_name: coolify-realtime container_name: coolify-realtime
restart: always restart: always

View File

@@ -1,20 +1,18 @@
# Versions # Versions
# https://hub.docker.com/_/alpine # https://hub.docker.com/_/alpine
ARG BASE_IMAGE=alpine:3.21 ARG BASE_IMAGE=alpine:3.21
# https://download.docker.com/linux/static/stable/ # https://download.docker.com/linux/static/stable/
ARG DOCKER_VERSION=27.4.1 ARG DOCKER_VERSION=28.0.0
# https://github.com/docker/compose/releases # https://github.com/docker/compose/releases
ARG DOCKER_COMPOSE_VERSION=2.32.2 ARG DOCKER_COMPOSE_VERSION=2.33.1
# https://github.com/docker/buildx/releases # https://github.com/docker/buildx/releases
ARG DOCKER_BUILDX_VERSION=0.19.3 ARG DOCKER_BUILDX_VERSION=0.21.1
# https://github.com/buildpacks/pack/releases # https://github.com/buildpacks/pack/releases
ARG PACK_VERSION=0.36.2 ARG PACK_VERSION=0.36.4
# https://github.com/railwayapp/nixpacks/releases # https://github.com/railwayapp/nixpacks/releases
ARG NIXPACKS_VERSION=1.29.0 ARG NIXPACKS_VERSION=1.33.0
# https://github.com/minio/mc/releases # https://github.com/minio/mc/releases
ARG MINIO_VERSION=RELEASE.2024-11-21T17-21-54Z ARG MINIO_VERSION=RELEASE.2025-02-15T10-36-16Z
FROM minio/mc:${MINIO_VERSION} AS minio-client FROM minio/mc:${MINIO_VERSION} AS minio-client

View File

@@ -2,7 +2,7 @@
# https://github.com/soketi/soketi/releases # https://github.com/soketi/soketi/releases
ARG SOKETI_VERSION=1.6-16-alpine ARG SOKETI_VERSION=1.6-16-alpine
# https://github.com/cloudflare/cloudflared/releases # https://github.com/cloudflare/cloudflared/releases
ARG CLOUDFLARED_VERSION=2025.1.0 ARG CLOUDFLARED_VERSION=2025.2.0
FROM quay.io/soketi/soketi:${SOKETI_VERSION} FROM quay.io/soketi/soketi:${SOKETI_VERSION}

View File

@@ -11,7 +11,7 @@
"cookie": "1.0.2", "cookie": "1.0.2",
"dotenv": "16.4.7", "dotenv": "16.4.7",
"node-pty": "1.0.0", "node-pty": "1.0.0",
"ws": "8.18.0" "ws": "8.18.1"
} }
}, },
"node_modules/@xterm/addon-fit": { "node_modules/@xterm/addon-fit": {
@@ -46,6 +46,19 @@
"proxy-from-env": "^1.1.0" "proxy-from-env": "^1.1.0"
} }
}, },
"node_modules/call-bind-apply-helpers": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
"integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0",
"function-bind": "^1.1.2"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/combined-stream": { "node_modules/combined-stream": {
"version": "1.0.8", "version": "1.0.8",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
@@ -88,6 +101,65 @@
"url": "https://dotenvx.com" "url": "https://dotenvx.com"
} }
}, },
"node_modules/dunder-proto": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
"integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
"license": "MIT",
"dependencies": {
"call-bind-apply-helpers": "^1.0.1",
"es-errors": "^1.3.0",
"gopd": "^1.2.0"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/es-define-property": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
"integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
}
},
"node_modules/es-errors": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
"integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
}
},
"node_modules/es-object-atoms": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
"integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/es-set-tostringtag": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
"integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0",
"get-intrinsic": "^1.2.6",
"has-tostringtag": "^1.0.2",
"hasown": "^2.0.2"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/follow-redirects": { "node_modules/follow-redirects": {
"version": "1.15.9", "version": "1.15.9",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz",
@@ -109,19 +181,126 @@
} }
}, },
"node_modules/form-data": { "node_modules/form-data": {
"version": "4.0.1", "version": "4.0.2",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.2.tgz",
"integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==", "integrity": "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"asynckit": "^0.4.0", "asynckit": "^0.4.0",
"combined-stream": "^1.0.8", "combined-stream": "^1.0.8",
"es-set-tostringtag": "^2.1.0",
"mime-types": "^2.1.12" "mime-types": "^2.1.12"
}, },
"engines": { "engines": {
"node": ">= 6" "node": ">= 6"
} }
}, },
"node_modules/function-bind": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/get-intrinsic": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
"integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
"license": "MIT",
"dependencies": {
"call-bind-apply-helpers": "^1.0.2",
"es-define-property": "^1.0.1",
"es-errors": "^1.3.0",
"es-object-atoms": "^1.1.1",
"function-bind": "^1.1.2",
"get-proto": "^1.0.1",
"gopd": "^1.2.0",
"has-symbols": "^1.1.0",
"hasown": "^2.0.2",
"math-intrinsics": "^1.1.0"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/get-proto": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
"integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
"license": "MIT",
"dependencies": {
"dunder-proto": "^1.0.1",
"es-object-atoms": "^1.0.0"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/gopd": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
"integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/has-symbols": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
"integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/has-tostringtag": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
"integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
"license": "MIT",
"dependencies": {
"has-symbols": "^1.0.3"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/hasown": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
"integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
"license": "MIT",
"dependencies": {
"function-bind": "^1.1.2"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/math-intrinsics": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
"integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
}
},
"node_modules/mime-db": { "node_modules/mime-db": {
"version": "1.52.0", "version": "1.52.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
@@ -144,9 +323,9 @@
} }
}, },
"node_modules/nan": { "node_modules/nan": {
"version": "2.22.0", "version": "2.22.1",
"resolved": "https://registry.npmjs.org/nan/-/nan-2.22.0.tgz", "resolved": "https://registry.npmjs.org/nan/-/nan-2.22.1.tgz",
"integrity": "sha512-nbajikzWTMwsW+eSsNm3QwlOs7het9gGJU5dDZzRTQGk03vyBOauxgI4VakDzE0PtsGTmXPsXTbbjVhRwR5mpw==", "integrity": "sha512-pfRR4ZcNTSm2ZFHaztuvbICf+hyiG6ecA06SfAxoPmuHjvMu0KUIae7Y8GyVkbBqeEIidsmXeYooWIX9+qjfRQ==",
"license": "MIT" "license": "MIT"
}, },
"node_modules/node-pty": { "node_modules/node-pty": {
@@ -166,9 +345,9 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/ws": { "node_modules/ws": {
"version": "8.18.0", "version": "8.18.1",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.1.tgz",
"integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", "integrity": "sha512-RKW2aJZMXeMxVpnZ6bck+RswznaxmzdULiBr6KY7XkTnW8uvt0iT9H5DkHUChXrc+uurzwa0rVI16n/Xzjdz1w==",
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">=10.0.0" "node": ">=10.0.0"

View File

@@ -8,6 +8,6 @@
"axios": "1.7.9", "axios": "1.7.9",
"dotenv": "16.4.7", "dotenv": "16.4.7",
"node-pty": "1.0.0", "node-pty": "1.0.0",
"ws": "8.18.0" "ws": "8.18.1"
} }
} }

View File

@@ -2,9 +2,9 @@
# https://hub.docker.com/r/serversideup/php/tags?name=8.4-fpm-nginx-alpine # https://hub.docker.com/r/serversideup/php/tags?name=8.4-fpm-nginx-alpine
ARG SERVERSIDEUP_PHP_VERSION=8.4-fpm-nginx-alpine ARG SERVERSIDEUP_PHP_VERSION=8.4-fpm-nginx-alpine
# https://github.com/minio/mc/releases # https://github.com/minio/mc/releases
ARG MINIO_VERSION=RELEASE.2024-11-21T17-21-54Z ARG MINIO_VERSION=RELEASE.2025-02-15T10-36-16Z
# https://github.com/cloudflare/cloudflared/releases # https://github.com/cloudflare/cloudflared/releases
ARG CLOUDFLARED_VERSION=2025.1.0 ARG CLOUDFLARED_VERSION=2025.2.0
# https://www.postgresql.org/support/versioning/ # https://www.postgresql.org/support/versioning/
ARG POSTGRES_VERSION=15 ARG POSTGRES_VERSION=15

View File

@@ -2,9 +2,9 @@
# https://hub.docker.com/r/serversideup/php/tags?name=8.4-fpm-nginx-alpine # https://hub.docker.com/r/serversideup/php/tags?name=8.4-fpm-nginx-alpine
ARG SERVERSIDEUP_PHP_VERSION=8.4-fpm-nginx-alpine ARG SERVERSIDEUP_PHP_VERSION=8.4-fpm-nginx-alpine
# https://github.com/minio/mc/releases # https://github.com/minio/mc/releases
ARG MINIO_VERSION=RELEASE.2024-11-21T17-21-54Z ARG MINIO_VERSION=RELEASE.2025-02-15T10-36-16Z
# https://github.com/cloudflare/cloudflared/releases # https://github.com/cloudflare/cloudflared/releases
ARG CLOUDFLARED_VERSION=2025.1.0 ARG CLOUDFLARED_VERSION=2025.2.0
# https://www.postgresql.org/support/versioning/ # https://www.postgresql.org/support/versioning/
ARG POSTGRES_VERSION=15 ARG POSTGRES_VERSION=15

View File

@@ -1,10 +1,10 @@
# Versions # Versions
# https://download.docker.com/linux/static/stable/ # https://download.docker.com/linux/static/stable/
ARG DOCKER_VERSION=27.4.1 ARG DOCKER_VERSION=28.0.0
# https://github.com/docker/compose/releases # https://github.com/docker/compose/releases
ARG DOCKER_COMPOSE_VERSION=2.32.2 ARG DOCKER_COMPOSE_VERSION=2.33.1
# https://github.com/docker/buildx/releases # https://github.com/docker/buildx/releases
ARG DOCKER_BUILDX_VERSION=0.19.3 ARG DOCKER_BUILDX_VERSION=0.21.1
FROM debian:12-slim FROM debian:12-slim

View File

@@ -61,7 +61,7 @@ services:
retries: 10 retries: 10
timeout: 2s timeout: 2s
soketi: soketi:
image: 'ghcr.io/coollabsio/coolify-realtime:1.0.5' image: 'ghcr.io/coollabsio/coolify-realtime:1.0.6'
ports: ports:
- "${SOKETI_PORT:-6001}:6001" - "${SOKETI_PORT:-6001}:6001"
- "6002:6002" - "6002:6002"

View File

@@ -1,16 +1,16 @@
{ {
"coolify": { "coolify": {
"v4": { "v4": {
"version": "4.0.0-beta.382" "version": "4.0.0-beta.397"
}, },
"nightly": { "nightly": {
"version": "4.0.0-beta.383" "version": "4.0.0-beta.398"
}, },
"helper": { "helper": {
"version": "1.0.4" "version": "1.0.7"
}, },
"realtime": { "realtime": {
"version": "1.0.5" "version": "1.0.6"
}, },
"sentinel": { "sentinel": {
"version": "0.0.15" "version": "0.0.15"

369
package-lock.json generated
View File

@@ -10,19 +10,19 @@
"@tailwindcss/typography": "0.5.16", "@tailwindcss/typography": "0.5.16",
"@xterm/addon-fit": "^0.10.0", "@xterm/addon-fit": "^0.10.0",
"@xterm/xterm": "^5.5.0", "@xterm/xterm": "^5.5.0",
"ioredis": "5.4.2" "ioredis": "5.5.0"
}, },
"devDependencies": { "devDependencies": {
"@vitejs/plugin-vue": "5.2.1", "@vitejs/plugin-vue": "5.2.1",
"autoprefixer": "10.4.20", "autoprefixer": "10.4.20",
"axios": "1.7.9", "axios": "1.7.9",
"laravel-echo": "1.17.1", "laravel-echo": "2.0.2",
"laravel-vite-plugin": "1.1.1", "laravel-vite-plugin": "^1.2.0",
"postcss": "8.4.49", "postcss": "8.5.3",
"pusher-js": "8.4.0-rc2", "pusher-js": "8.4.0",
"tailwind-scrollbar": "^3.1.0", "tailwind-scrollbar": "^3.1.0",
"tailwindcss": "3.4.17", "tailwindcss": "3.4.17",
"vite": "6.0.11", "vite": "^6.1.1",
"vue": "3.5.13" "vue": "3.5.13"
} }
}, },
@@ -535,9 +535,9 @@
} }
}, },
"node_modules/@jridgewell/gen-mapping": { "node_modules/@jridgewell/gen-mapping": {
"version": "0.3.5", "version": "0.3.8",
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz",
"integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@jridgewell/set-array": "^1.2.1", "@jridgewell/set-array": "^1.2.1",
@@ -586,6 +586,7 @@
"version": "2.1.5", "version": "2.1.5",
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
"integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
"license": "MIT",
"dependencies": { "dependencies": {
"@nodelib/fs.stat": "2.0.5", "@nodelib/fs.stat": "2.0.5",
"run-parallel": "^1.1.9" "run-parallel": "^1.1.9"
@@ -598,6 +599,7 @@
"version": "2.0.5", "version": "2.0.5",
"resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
"integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
"license": "MIT",
"engines": { "engines": {
"node": ">= 8" "node": ">= 8"
} }
@@ -606,6 +608,7 @@
"version": "1.2.8", "version": "1.2.8",
"resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
"integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
"license": "MIT",
"dependencies": { "dependencies": {
"@nodelib/fs.scandir": "2.1.5", "@nodelib/fs.scandir": "2.1.5",
"fastq": "^1.6.0" "fastq": "^1.6.0"
@@ -625,9 +628,9 @@
} }
}, },
"node_modules/@rollup/rollup-android-arm-eabi": { "node_modules/@rollup/rollup-android-arm-eabi": {
"version": "4.25.0", "version": "4.34.8",
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.25.0.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.34.8.tgz",
"integrity": "sha512-CC/ZqFZwlAIbU1wUPisHyV/XRc5RydFrNLtgl3dGYskdwPZdt4HERtKm50a/+DtTlKeCq9IXFEWR+P6blwjqBA==", "integrity": "sha512-q217OSE8DTp8AFHuNHXo0Y86e1wtlfVrXiAlwkIvGRQv9zbc6mE3sjIVfwI8sYUyNxwOg0j/Vm1RKM04JcWLJw==",
"cpu": [ "cpu": [
"arm" "arm"
], ],
@@ -639,9 +642,9 @@
] ]
}, },
"node_modules/@rollup/rollup-android-arm64": { "node_modules/@rollup/rollup-android-arm64": {
"version": "4.25.0", "version": "4.34.8",
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.25.0.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.34.8.tgz",
"integrity": "sha512-/Y76tmLGUJqVBXXCfVS8Q8FJqYGhgH4wl4qTA24E9v/IJM0XvJCGQVSW1QZ4J+VURO9h8YCa28sTFacZXwK7Rg==", "integrity": "sha512-Gigjz7mNWaOL9wCggvoK3jEIUUbGul656opstjaUSGC3eT0BM7PofdAJaBfPFWWkXNVAXbaQtC99OCg4sJv70Q==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -653,9 +656,9 @@
] ]
}, },
"node_modules/@rollup/rollup-darwin-arm64": { "node_modules/@rollup/rollup-darwin-arm64": {
"version": "4.25.0", "version": "4.34.8",
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.25.0.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.34.8.tgz",
"integrity": "sha512-YVT6L3UrKTlC0FpCZd0MGA7NVdp7YNaEqkENbWQ7AOVOqd/7VzyHpgIpc1mIaxRAo1ZsJRH45fq8j4N63I/vvg==", "integrity": "sha512-02rVdZ5tgdUNRxIUrFdcMBZQoaPMrxtwSb+/hOfBdqkatYHR3lZ2A2EGyHq2sGOd0Owk80oV3snlDASC24He3Q==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -667,9 +670,9 @@
] ]
}, },
"node_modules/@rollup/rollup-darwin-x64": { "node_modules/@rollup/rollup-darwin-x64": {
"version": "4.25.0", "version": "4.34.8",
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.25.0.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.34.8.tgz",
"integrity": "sha512-ZRL+gexs3+ZmmWmGKEU43Bdn67kWnMeWXLFhcVv5Un8FQcx38yulHBA7XR2+KQdYIOtD0yZDWBCudmfj6lQJoA==", "integrity": "sha512-qIP/elwR/tq/dYRx3lgwK31jkZvMiD6qUtOycLhTzCvrjbZ3LjQnEM9rNhSGpbLXVJYQ3rq39A6Re0h9tU2ynw==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@@ -681,9 +684,9 @@
] ]
}, },
"node_modules/@rollup/rollup-freebsd-arm64": { "node_modules/@rollup/rollup-freebsd-arm64": {
"version": "4.25.0", "version": "4.34.8",
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.25.0.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.34.8.tgz",
"integrity": "sha512-xpEIXhiP27EAylEpreCozozsxWQ2TJbOLSivGfXhU4G1TBVEYtUPi2pOZBnvGXHyOdLAUUhPnJzH3ah5cqF01g==", "integrity": "sha512-IQNVXL9iY6NniYbTaOKdrlVP3XIqazBgJOVkddzJlqnCpRi/yAeSOa8PLcECFSQochzqApIOE1GHNu3pCz+BDA==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -695,9 +698,9 @@
] ]
}, },
"node_modules/@rollup/rollup-freebsd-x64": { "node_modules/@rollup/rollup-freebsd-x64": {
"version": "4.25.0", "version": "4.34.8",
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.25.0.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.34.8.tgz",
"integrity": "sha512-sC5FsmZGlJv5dOcURrsnIK7ngc3Kirnx3as2XU9uER+zjfyqIjdcMVgzy4cOawhsssqzoAX19qmxgJ8a14Qrqw==", "integrity": "sha512-TYXcHghgnCqYFiE3FT5QwXtOZqDj5GmaFNTNt3jNC+vh22dc/ukG2cG+pi75QO4kACohZzidsq7yKTKwq/Jq7Q==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@@ -709,9 +712,9 @@
] ]
}, },
"node_modules/@rollup/rollup-linux-arm-gnueabihf": { "node_modules/@rollup/rollup-linux-arm-gnueabihf": {
"version": "4.25.0", "version": "4.34.8",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.25.0.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.34.8.tgz",
"integrity": "sha512-uD/dbLSs1BEPzg564TpRAQ/YvTnCds2XxyOndAO8nJhaQcqQGFgv/DAVko/ZHap3boCvxnzYMa3mTkV/B/3SWA==", "integrity": "sha512-A4iphFGNkWRd+5m3VIGuqHnG3MVnqKe7Al57u9mwgbyZ2/xF9Jio72MaY7xxh+Y87VAHmGQr73qoKL9HPbXj1g==",
"cpu": [ "cpu": [
"arm" "arm"
], ],
@@ -723,9 +726,9 @@
] ]
}, },
"node_modules/@rollup/rollup-linux-arm-musleabihf": { "node_modules/@rollup/rollup-linux-arm-musleabihf": {
"version": "4.25.0", "version": "4.34.8",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.25.0.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.34.8.tgz",
"integrity": "sha512-ZVt/XkrDlQWegDWrwyC3l0OfAF7yeJUF4fq5RMS07YM72BlSfn2fQQ6lPyBNjt+YbczMguPiJoCfaQC2dnflpQ==", "integrity": "sha512-S0lqKLfTm5u+QTxlFiAnb2J/2dgQqRy/XvziPtDd1rKZFXHTyYLoVL58M/XFwDI01AQCDIevGLbQrMAtdyanpA==",
"cpu": [ "cpu": [
"arm" "arm"
], ],
@@ -737,9 +740,9 @@
] ]
}, },
"node_modules/@rollup/rollup-linux-arm64-gnu": { "node_modules/@rollup/rollup-linux-arm64-gnu": {
"version": "4.25.0", "version": "4.34.8",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.25.0.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.34.8.tgz",
"integrity": "sha512-qboZ+T0gHAW2kkSDPHxu7quaFaaBlynODXpBVnPxUgvWYaE84xgCKAPEYE+fSMd3Zv5PyFZR+L0tCdYCMAtG0A==", "integrity": "sha512-jpz9YOuPiSkL4G4pqKrus0pn9aYwpImGkosRKwNi+sJSkz+WU3anZe6hi73StLOQdfXYXC7hUfsQlTnjMd3s1A==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -751,9 +754,9 @@
] ]
}, },
"node_modules/@rollup/rollup-linux-arm64-musl": { "node_modules/@rollup/rollup-linux-arm64-musl": {
"version": "4.25.0", "version": "4.34.8",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.25.0.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.34.8.tgz",
"integrity": "sha512-ndWTSEmAaKr88dBuogGH2NZaxe7u2rDoArsejNslugHZ+r44NfWiwjzizVS1nUOHo+n1Z6qV3X60rqE/HlISgw==", "integrity": "sha512-KdSfaROOUJXgTVxJNAZ3KwkRc5nggDk+06P6lgi1HLv1hskgvxHUKZ4xtwHkVYJ1Rep4GNo+uEfycCRRxht7+Q==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -764,10 +767,24 @@
"linux" "linux"
] ]
}, },
"node_modules/@rollup/rollup-linux-loongarch64-gnu": {
"version": "4.34.8",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.34.8.tgz",
"integrity": "sha512-NyF4gcxwkMFRjgXBM6g2lkT58OWztZvw5KkV2K0qqSnUEqCVcqdh2jN4gQrTn/YUpAcNKyFHfoOZEer9nwo6uQ==",
"cpu": [
"loong64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@rollup/rollup-linux-powerpc64le-gnu": { "node_modules/@rollup/rollup-linux-powerpc64le-gnu": {
"version": "4.25.0", "version": "4.34.8",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.25.0.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.34.8.tgz",
"integrity": "sha512-BVSQvVa2v5hKwJSy6X7W1fjDex6yZnNKy3Kx1JGimccHft6HV0THTwNtC2zawtNXKUu+S5CjXslilYdKBAadzA==", "integrity": "sha512-LMJc999GkhGvktHU85zNTDImZVUCJ1z/MbAJTnviiWmmjyckP5aQsHtcujMjpNdMZPT2rQEDBlJfubhs3jsMfw==",
"cpu": [ "cpu": [
"ppc64" "ppc64"
], ],
@@ -779,9 +796,9 @@
] ]
}, },
"node_modules/@rollup/rollup-linux-riscv64-gnu": { "node_modules/@rollup/rollup-linux-riscv64-gnu": {
"version": "4.25.0", "version": "4.34.8",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.25.0.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.34.8.tgz",
"integrity": "sha512-G4hTREQrIdeV0PE2JruzI+vXdRnaK1pg64hemHq2v5fhv8C7WjVaeXc9P5i4Q5UC06d/L+zA0mszYIKl+wY8oA==", "integrity": "sha512-xAQCAHPj8nJq1PI3z8CIZzXuXCstquz7cIOL73HHdXiRcKk8Ywwqtx2wrIy23EcTn4aZ2fLJNBB8d0tQENPCmw==",
"cpu": [ "cpu": [
"riscv64" "riscv64"
], ],
@@ -793,9 +810,9 @@
] ]
}, },
"node_modules/@rollup/rollup-linux-s390x-gnu": { "node_modules/@rollup/rollup-linux-s390x-gnu": {
"version": "4.25.0", "version": "4.34.8",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.25.0.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.34.8.tgz",
"integrity": "sha512-9T/w0kQ+upxdkFL9zPVB6zy9vWW1deA3g8IauJxojN4bnz5FwSsUAD034KpXIVX5j5p/rn6XqumBMxfRkcHapQ==", "integrity": "sha512-DdePVk1NDEuc3fOe3dPPTb+rjMtuFw89gw6gVWxQFAuEqqSdDKnrwzZHrUYdac7A7dXl9Q2Vflxpme15gUWQFA==",
"cpu": [ "cpu": [
"s390x" "s390x"
], ],
@@ -807,9 +824,9 @@
] ]
}, },
"node_modules/@rollup/rollup-linux-x64-gnu": { "node_modules/@rollup/rollup-linux-x64-gnu": {
"version": "4.25.0", "version": "4.34.8",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.25.0.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.34.8.tgz",
"integrity": "sha512-ThcnU0EcMDn+J4B9LD++OgBYxZusuA7iemIIiz5yzEcFg04VZFzdFjuwPdlURmYPZw+fgVrFzj4CA64jSTG4Ig==", "integrity": "sha512-8y7ED8gjxITUltTUEJLQdgpbPh1sUQ0kMTmufRF/Ns5tI9TNMNlhWtmPKKHCU0SilX+3MJkZ0zERYYGIVBYHIA==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@@ -821,9 +838,9 @@
] ]
}, },
"node_modules/@rollup/rollup-linux-x64-musl": { "node_modules/@rollup/rollup-linux-x64-musl": {
"version": "4.25.0", "version": "4.34.8",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.25.0.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.34.8.tgz",
"integrity": "sha512-zx71aY2oQxGxAT1JShfhNG79PnjYhMC6voAjzpu/xmMjDnKNf6Nl/xv7YaB/9SIa9jDYf8RBPWEnjcdlhlv1rQ==", "integrity": "sha512-SCXcP0ZpGFIe7Ge+McxY5zKxiEI5ra+GT3QRxL0pMMtxPfpyLAKleZODi1zdRHkz5/BhueUrYtYVgubqe9JBNQ==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@@ -835,9 +852,9 @@
] ]
}, },
"node_modules/@rollup/rollup-win32-arm64-msvc": { "node_modules/@rollup/rollup-win32-arm64-msvc": {
"version": "4.25.0", "version": "4.34.8",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.25.0.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.34.8.tgz",
"integrity": "sha512-JT8tcjNocMs4CylWY/CxVLnv8e1lE7ff1fi6kbGocWwxDq9pj30IJ28Peb+Y8yiPNSF28oad42ApJB8oUkwGww==", "integrity": "sha512-YHYsgzZgFJzTRbth4h7Or0m5O74Yda+hLin0irAIobkLQFRQd1qWmnoVfwmKm9TXIZVAD0nZ+GEb2ICicLyCnQ==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -849,9 +866,9 @@
] ]
}, },
"node_modules/@rollup/rollup-win32-ia32-msvc": { "node_modules/@rollup/rollup-win32-ia32-msvc": {
"version": "4.25.0", "version": "4.34.8",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.25.0.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.34.8.tgz",
"integrity": "sha512-dRLjLsO3dNOfSN6tjyVlG+Msm4IiZnGkuZ7G5NmpzwF9oOc582FZG05+UdfTbz5Jd4buK/wMb6UeHFhG18+OEg==", "integrity": "sha512-r3NRQrXkHr4uWy5TOjTpTYojR9XmF0j/RYgKCef+Ag46FWUTltm5ziticv8LdNsDMehjJ543x/+TJAek/xBA2w==",
"cpu": [ "cpu": [
"ia32" "ia32"
], ],
@@ -863,9 +880,9 @@
] ]
}, },
"node_modules/@rollup/rollup-win32-x64-msvc": { "node_modules/@rollup/rollup-win32-x64-msvc": {
"version": "4.25.0", "version": "4.34.8",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.25.0.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.34.8.tgz",
"integrity": "sha512-/RqrIFtLB926frMhZD0a5oDa4eFIbyNEwLLloMTEjmqfwZWXywwVVOVmwTsuyhC9HKkVEZcOOi+KV4U9wmOdlg==", "integrity": "sha512-U0FaE5O1BCpZSeE6gBl3c5ObhePQSfk9vDRToMmTkbhCOgW4jqvtS5LGyQ76L1fH8sM0keRp4uDTsbjiUyjk0g==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@@ -1155,7 +1172,8 @@
"node_modules/arg": { "node_modules/arg": {
"version": "5.0.2", "version": "5.0.2",
"resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz",
"integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==" "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==",
"license": "MIT"
}, },
"node_modules/asynckit": { "node_modules/asynckit": {
"version": "0.4.0", "version": "0.4.0",
@@ -1248,9 +1266,9 @@
} }
}, },
"node_modules/browserslist": { "node_modules/browserslist": {
"version": "4.24.2", "version": "4.24.4",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.2.tgz", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.4.tgz",
"integrity": "sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg==", "integrity": "sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==",
"dev": true, "dev": true,
"funding": [ "funding": [
{ {
@@ -1268,9 +1286,9 @@
], ],
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"caniuse-lite": "^1.0.30001669", "caniuse-lite": "^1.0.30001688",
"electron-to-chromium": "^1.5.41", "electron-to-chromium": "^1.5.73",
"node-releases": "^2.0.18", "node-releases": "^2.0.19",
"update-browserslist-db": "^1.1.1" "update-browserslist-db": "^1.1.1"
}, },
"bin": { "bin": {
@@ -1284,14 +1302,15 @@
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz",
"integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==",
"license": "MIT",
"engines": { "engines": {
"node": ">= 6" "node": ">= 6"
} }
}, },
"node_modules/caniuse-lite": { "node_modules/caniuse-lite": {
"version": "1.0.30001680", "version": "1.0.30001700",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001680.tgz", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001700.tgz",
"integrity": "sha512-rPQy70G6AGUMnbwS1z6Xg+RkHYPAi18ihs47GH0jcxIG7wArmPgY3XbS2sRdBbxJljp3thdT8BIqv9ccCypiPA==", "integrity": "sha512-2S6XIXwaE7K7erT8dY+kLQcpa5ms63XlRkMkReXjle+kf6c5g38vyMl+Z5y8dSxOFDhcFe+nxnn261PLxBSQsQ==",
"dev": true, "dev": true,
"funding": [ "funding": [
{ {
@@ -1459,12 +1478,14 @@
"node_modules/didyoumean": { "node_modules/didyoumean": {
"version": "1.2.2", "version": "1.2.2",
"resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz",
"integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==" "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==",
"license": "Apache-2.0"
}, },
"node_modules/dlv": { "node_modules/dlv": {
"version": "1.1.3", "version": "1.1.3",
"resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz",
"integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==" "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==",
"license": "MIT"
}, },
"node_modules/eastasianwidth": { "node_modules/eastasianwidth": {
"version": "0.2.0", "version": "0.2.0",
@@ -1473,9 +1494,9 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/electron-to-chromium": { "node_modules/electron-to-chromium": {
"version": "1.5.55", "version": "1.5.103",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.55.tgz", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.103.tgz",
"integrity": "sha512-6maZ2ASDOTBtjt9FhqYPRnbvKU5tjG0IN9SztUOWYw2AzNDNpKJYLJmlK0/En4Hs/aiWnB+JZ+gW19PIGszgKg==", "integrity": "sha512-P6+XzIkfndgsrjROJWfSvVEgNHtPgbhVyTkwLjUM2HU/h7pZRORgaTlHqfAikqxKmdJMLW8fftrdGWbd/Ds0FA==",
"dev": true, "dev": true,
"license": "ISC" "license": "ISC"
}, },
@@ -1557,15 +1578,16 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/fast-glob": { "node_modules/fast-glob": {
"version": "3.3.2", "version": "3.3.3",
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz",
"integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==",
"license": "MIT",
"dependencies": { "dependencies": {
"@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.stat": "^2.0.2",
"@nodelib/fs.walk": "^1.2.3", "@nodelib/fs.walk": "^1.2.3",
"glob-parent": "^5.1.2", "glob-parent": "^5.1.2",
"merge2": "^1.3.0", "merge2": "^1.3.0",
"micromatch": "^4.0.4" "micromatch": "^4.0.8"
}, },
"engines": { "engines": {
"node": ">=8.6.0" "node": ">=8.6.0"
@@ -1575,6 +1597,7 @@
"version": "5.1.2", "version": "5.1.2",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
"license": "ISC",
"dependencies": { "dependencies": {
"is-glob": "^4.0.1" "is-glob": "^4.0.1"
}, },
@@ -1583,9 +1606,10 @@
} }
}, },
"node_modules/fastq": { "node_modules/fastq": {
"version": "1.15.0", "version": "1.19.0",
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.0.tgz",
"integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", "integrity": "sha512-7SFSRCNjBQIZH/xZR3iy5iQYR8aGBE0h3VG6/cwlbrpdciNYBMotQav8c1XI3HjHH+NikUpP53nPdlZSdWmFzA==",
"license": "ISC",
"dependencies": { "dependencies": {
"reusify": "^1.0.4" "reusify": "^1.0.4"
} }
@@ -1656,6 +1680,7 @@
"resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz",
"integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==", "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==",
"dev": true, "dev": true,
"license": "MIT",
"engines": { "engines": {
"node": "*" "node": "*"
}, },
@@ -1710,6 +1735,7 @@
"version": "6.0.2", "version": "6.0.2",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
"integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
"license": "ISC",
"dependencies": { "dependencies": {
"is-glob": "^4.0.3" "is-glob": "^4.0.3"
}, },
@@ -1729,18 +1755,10 @@
"node": ">= 0.4" "node": ">= 0.4"
} }
}, },
"node_modules/immutable": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.0.tgz",
"integrity": "sha512-0AOCmOip+xgJwEVTQj1EfiDDOkPmuyllDuTuEX+DDXUgapLAsBIfkg3sxCYyCEA8mQqZrrxPUGjcOQ2JS3WLkg==",
"dev": true,
"optional": true,
"peer": true
},
"node_modules/ioredis": { "node_modules/ioredis": {
"version": "5.4.2", "version": "5.5.0",
"resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.4.2.tgz", "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.5.0.tgz",
"integrity": "sha512-0SZXGNGZ+WzISQ67QDyZ2x0+wVxjjUndtD8oSeik/4ajifeiRufed8fCb8QW8VMyi4MXcS+UO1k/0NGhvq1PAg==", "integrity": "sha512-7CutT89g23FfSa8MDoIFs2GYYa0PaNiW/OrT+nRyjRXHDZd17HmIgy+reOQ/yhh72NznNjGuS8kbCAcA4Ro4mw==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@ioredis/commands": "^1.1.1", "@ioredis/commands": "^1.1.1",
@@ -1773,9 +1791,9 @@
} }
}, },
"node_modules/is-core-module": { "node_modules/is-core-module": {
"version": "2.15.1", "version": "2.16.1",
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz",
"integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"hasown": "^2.0.2" "hasown": "^2.0.2"
@@ -1854,19 +1872,19 @@
} }
}, },
"node_modules/laravel-echo": { "node_modules/laravel-echo": {
"version": "1.17.1", "version": "2.0.2",
"resolved": "https://registry.npmjs.org/laravel-echo/-/laravel-echo-1.17.1.tgz", "resolved": "https://registry.npmjs.org/laravel-echo/-/laravel-echo-2.0.2.tgz",
"integrity": "sha512-ORWc4vDfnBj/Oe5ThZ5kYyGItRjLDqAQUyhD/7UhehUOqc+s5x9HEBjtMVludNMP6VuXw6t7Uxt8bp63kaTofg==", "integrity": "sha512-Ciai6hA7r35MFqNRb8G034cvm9WiveSTFQQKRGJhWtZGbng7C8BBa5QvqDxk/Mw5GeJ+q19jrEwQhf7r1b1lcg==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">=10" "node": ">=20"
} }
}, },
"node_modules/laravel-vite-plugin": { "node_modules/laravel-vite-plugin": {
"version": "1.1.1", "version": "1.2.0",
"resolved": "https://registry.npmjs.org/laravel-vite-plugin/-/laravel-vite-plugin-1.1.1.tgz", "resolved": "https://registry.npmjs.org/laravel-vite-plugin/-/laravel-vite-plugin-1.2.0.tgz",
"integrity": "sha512-HMZXpoSs1OR+7Lw1+g4Iy/s3HF3Ldl8KxxYT2Ot8pEB4XB/QRuZeWgDYJdu552UN03YRSRNK84CLC9NzYRtncA==", "integrity": "sha512-R0pJ+IcTVeqEMoKz/B2Ij57QVq3sFTABiFmb06gAwFdivbOgsUtuhX6N2MGLEArajrS3U5JbberzwOe7uXHMHQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@@ -1946,6 +1964,7 @@
"version": "1.4.1", "version": "1.4.1",
"resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
"integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
"license": "MIT",
"engines": { "engines": {
"node": ">= 8" "node": ">= 8"
} }
@@ -1954,6 +1973,7 @@
"version": "4.0.8", "version": "4.0.8",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
"integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
"license": "MIT",
"dependencies": { "dependencies": {
"braces": "^3.0.3", "braces": "^3.0.3",
"picomatch": "^2.3.1" "picomatch": "^2.3.1"
@@ -2050,9 +2070,9 @@
} }
}, },
"node_modules/node-releases": { "node_modules/node-releases": {
"version": "2.0.18", "version": "2.0.19",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz",
"integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==", "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==",
"dev": true, "dev": true,
"license": "MIT" "license": "MIT"
}, },
@@ -2069,6 +2089,7 @@
"resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz",
"integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==",
"dev": true, "dev": true,
"license": "MIT",
"engines": { "engines": {
"node": ">=0.10.0" "node": ">=0.10.0"
} }
@@ -2086,6 +2107,7 @@
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz",
"integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==",
"license": "MIT",
"engines": { "engines": {
"node": ">= 6" "node": ">= 6"
} }
@@ -2108,7 +2130,8 @@
"node_modules/path-parse": { "node_modules/path-parse": {
"version": "1.0.7", "version": "1.0.7",
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
"license": "MIT"
}, },
"node_modules/path-scurry": { "node_modules/path-scurry": {
"version": "1.11.1", "version": "1.11.1",
@@ -2147,6 +2170,7 @@
"version": "2.3.0", "version": "2.3.0",
"resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
"integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==",
"license": "MIT",
"engines": { "engines": {
"node": ">=0.10.0" "node": ">=0.10.0"
} }
@@ -2161,9 +2185,9 @@
} }
}, },
"node_modules/postcss": { "node_modules/postcss": {
"version": "8.4.49", "version": "8.5.3",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz",
"integrity": "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==", "integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==",
"funding": [ "funding": [
{ {
"type": "opencollective", "type": "opencollective",
@@ -2180,7 +2204,7 @@
], ],
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"nanoid": "^3.3.7", "nanoid": "^3.3.8",
"picocolors": "^1.1.1", "picocolors": "^1.1.1",
"source-map-js": "^1.2.1" "source-map-js": "^1.2.1"
}, },
@@ -2192,6 +2216,7 @@
"version": "15.1.0", "version": "15.1.0",
"resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz",
"integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==",
"license": "MIT",
"dependencies": { "dependencies": {
"postcss-value-parser": "^4.0.0", "postcss-value-parser": "^4.0.0",
"read-cache": "^1.0.0", "read-cache": "^1.0.0",
@@ -2208,6 +2233,7 @@
"version": "4.0.1", "version": "4.0.1",
"resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz", "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz",
"integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==", "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==",
"license": "MIT",
"dependencies": { "dependencies": {
"camelcase-css": "^2.0.1" "camelcase-css": "^2.0.1"
}, },
@@ -2298,7 +2324,8 @@
"node_modules/postcss-value-parser": { "node_modules/postcss-value-parser": {
"version": "4.2.0", "version": "4.2.0",
"resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz",
"integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==",
"license": "MIT"
}, },
"node_modules/proxy-from-env": { "node_modules/proxy-from-env": {
"version": "1.1.0", "version": "1.1.0",
@@ -2307,10 +2334,11 @@
"dev": true "dev": true
}, },
"node_modules/pusher-js": { "node_modules/pusher-js": {
"version": "8.4.0-rc2", "version": "8.4.0",
"resolved": "https://registry.npmjs.org/pusher-js/-/pusher-js-8.4.0-rc2.tgz", "resolved": "https://registry.npmjs.org/pusher-js/-/pusher-js-8.4.0.tgz",
"integrity": "sha512-d87GjOEEl9QgO5BWmViSqW0LOzPvybvX6WA9zLUstNdB57jVJuR27zHkRnrav2a3+zAMlHbP2Og8wug+rG8T+g==", "integrity": "sha512-wp3HqIIUc1GRyu1XrP6m2dgyE9MoCsXVsWNlohj0rjSkLf+a0jLvEyVubdg58oMk7bhjBWnFClgp8jfAa6Ak4Q==",
"dev": true, "dev": true,
"license": "MIT",
"dependencies": { "dependencies": {
"tweetnacl": "^1.0.3" "tweetnacl": "^1.0.3"
} }
@@ -2332,12 +2360,14 @@
"type": "consulting", "type": "consulting",
"url": "https://feross.org/support" "url": "https://feross.org/support"
} }
] ],
"license": "MIT"
}, },
"node_modules/read-cache": { "node_modules/read-cache": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
"integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==",
"license": "MIT",
"dependencies": { "dependencies": {
"pify": "^2.3.0" "pify": "^2.3.0"
} }
@@ -2373,18 +2403,21 @@
} }
}, },
"node_modules/resolve": { "node_modules/resolve": {
"version": "1.22.8", "version": "1.22.10",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz",
"integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"is-core-module": "^2.13.0", "is-core-module": "^2.16.0",
"path-parse": "^1.0.7", "path-parse": "^1.0.7",
"supports-preserve-symlinks-flag": "^1.0.0" "supports-preserve-symlinks-flag": "^1.0.0"
}, },
"bin": { "bin": {
"resolve": "bin/resolve" "resolve": "bin/resolve"
}, },
"engines": {
"node": ">= 0.4"
},
"funding": { "funding": {
"url": "https://github.com/sponsors/ljharb" "url": "https://github.com/sponsors/ljharb"
} }
@@ -2393,15 +2426,16 @@
"version": "1.0.4", "version": "1.0.4",
"resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
"integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
"license": "MIT",
"engines": { "engines": {
"iojs": ">=1.0.0", "iojs": ">=1.0.0",
"node": ">=0.10.0" "node": ">=0.10.0"
} }
}, },
"node_modules/rollup": { "node_modules/rollup": {
"version": "4.25.0", "version": "4.34.8",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.25.0.tgz", "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.34.8.tgz",
"integrity": "sha512-uVbClXmR6wvx5R1M3Od4utyLUxrmOcEm3pAtMphn73Apq19PDtHpgZoEvqH2YnnaNUuvKmg2DgRd2Sqv+odyqg==", "integrity": "sha512-489gTVMzAYdiZHFVA/ig/iYFllCcWFHMvUHI1rpFmkoUtRlQxqh6/yiNqnYibjMZ2b/+FUQwldG+aLsEt6bglQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@@ -2415,24 +2449,25 @@
"npm": ">=8.0.0" "npm": ">=8.0.0"
}, },
"optionalDependencies": { "optionalDependencies": {
"@rollup/rollup-android-arm-eabi": "4.25.0", "@rollup/rollup-android-arm-eabi": "4.34.8",
"@rollup/rollup-android-arm64": "4.25.0", "@rollup/rollup-android-arm64": "4.34.8",
"@rollup/rollup-darwin-arm64": "4.25.0", "@rollup/rollup-darwin-arm64": "4.34.8",
"@rollup/rollup-darwin-x64": "4.25.0", "@rollup/rollup-darwin-x64": "4.34.8",
"@rollup/rollup-freebsd-arm64": "4.25.0", "@rollup/rollup-freebsd-arm64": "4.34.8",
"@rollup/rollup-freebsd-x64": "4.25.0", "@rollup/rollup-freebsd-x64": "4.34.8",
"@rollup/rollup-linux-arm-gnueabihf": "4.25.0", "@rollup/rollup-linux-arm-gnueabihf": "4.34.8",
"@rollup/rollup-linux-arm-musleabihf": "4.25.0", "@rollup/rollup-linux-arm-musleabihf": "4.34.8",
"@rollup/rollup-linux-arm64-gnu": "4.25.0", "@rollup/rollup-linux-arm64-gnu": "4.34.8",
"@rollup/rollup-linux-arm64-musl": "4.25.0", "@rollup/rollup-linux-arm64-musl": "4.34.8",
"@rollup/rollup-linux-powerpc64le-gnu": "4.25.0", "@rollup/rollup-linux-loongarch64-gnu": "4.34.8",
"@rollup/rollup-linux-riscv64-gnu": "4.25.0", "@rollup/rollup-linux-powerpc64le-gnu": "4.34.8",
"@rollup/rollup-linux-s390x-gnu": "4.25.0", "@rollup/rollup-linux-riscv64-gnu": "4.34.8",
"@rollup/rollup-linux-x64-gnu": "4.25.0", "@rollup/rollup-linux-s390x-gnu": "4.34.8",
"@rollup/rollup-linux-x64-musl": "4.25.0", "@rollup/rollup-linux-x64-gnu": "4.34.8",
"@rollup/rollup-win32-arm64-msvc": "4.25.0", "@rollup/rollup-linux-x64-musl": "4.34.8",
"@rollup/rollup-win32-ia32-msvc": "4.25.0", "@rollup/rollup-win32-arm64-msvc": "4.34.8",
"@rollup/rollup-win32-x64-msvc": "4.25.0", "@rollup/rollup-win32-ia32-msvc": "4.34.8",
"@rollup/rollup-win32-x64-msvc": "4.34.8",
"fsevents": "~2.3.2" "fsevents": "~2.3.2"
} }
}, },
@@ -2454,29 +2489,11 @@
"url": "https://feross.org/support" "url": "https://feross.org/support"
} }
], ],
"license": "MIT",
"dependencies": { "dependencies": {
"queue-microtask": "^1.2.2" "queue-microtask": "^1.2.2"
} }
}, },
"node_modules/sass": {
"version": "1.62.1",
"resolved": "https://registry.npmjs.org/sass/-/sass-1.62.1.tgz",
"integrity": "sha512-NHpxIzN29MXvWiuswfc1W3I0N8SXBd8UR26WntmDlRYf0bSADnwnOjsyMZ3lMezSlArD33Vs3YFhp7dWvL770A==",
"dev": true,
"optional": true,
"peer": true,
"dependencies": {
"chokidar": ">=3.0.0 <4.0.0",
"immutable": "^4.0.0",
"source-map-js": ">=0.6.2 <2.0.0"
},
"bin": {
"sass": "sass.js"
},
"engines": {
"node": ">=14.0.0"
}
},
"node_modules/shebang-command": { "node_modules/shebang-command": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
@@ -2646,6 +2663,7 @@
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
"integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
"license": "MIT",
"engines": { "engines": {
"node": ">= 0.4" "node": ">= 0.4"
}, },
@@ -2748,9 +2766,9 @@
"dev": true "dev": true
}, },
"node_modules/update-browserslist-db": { "node_modules/update-browserslist-db": {
"version": "1.1.1", "version": "1.1.2",
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.2.tgz",
"integrity": "sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==", "integrity": "sha512-PPypAm5qvlD7XMZC3BujecnaOxwhrtoFR+Dqkk5Aa/6DssiH0ibKoketaj9w8LP7Bont1rYeoV5plxD7RTEPRg==",
"dev": true, "dev": true,
"funding": [ "funding": [
{ {
@@ -2769,7 +2787,7 @@
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"escalade": "^3.2.0", "escalade": "^3.2.0",
"picocolors": "^1.1.0" "picocolors": "^1.1.1"
}, },
"bin": { "bin": {
"update-browserslist-db": "cli.js" "update-browserslist-db": "cli.js"
@@ -2784,15 +2802,15 @@
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
}, },
"node_modules/vite": { "node_modules/vite": {
"version": "6.0.11", "version": "6.1.1",
"resolved": "https://registry.npmjs.org/vite/-/vite-6.0.11.tgz", "resolved": "https://registry.npmjs.org/vite/-/vite-6.1.1.tgz",
"integrity": "sha512-4VL9mQPKoHy4+FE0NnRE/kbY51TOfaknxAjt3fJbGJxhIpBZiqVzlZDEesWWsuREXHwNdAoOFZ9MkPEVXczHwg==", "integrity": "sha512-4GgM54XrwRfrOp297aIYspIti66k56v16ZnqHvrIM7mG+HjDlAwS7p+Srr7J6fGvEdOJ5JcQ/D9T7HhtdXDTzA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"esbuild": "^0.24.2", "esbuild": "^0.24.2",
"postcss": "^8.4.49", "postcss": "^8.5.2",
"rollup": "^4.23.0" "rollup": "^4.30.1"
}, },
"bin": { "bin": {
"vite": "bin/vite.js" "vite": "bin/vite.js"
@@ -2856,10 +2874,11 @@
} }
}, },
"node_modules/vite-plugin-full-reload": { "node_modules/vite-plugin-full-reload": {
"version": "1.1.0", "version": "1.2.0",
"resolved": "https://registry.npmjs.org/vite-plugin-full-reload/-/vite-plugin-full-reload-1.1.0.tgz", "resolved": "https://registry.npmjs.org/vite-plugin-full-reload/-/vite-plugin-full-reload-1.2.0.tgz",
"integrity": "sha512-3cObNDzX6DdfhD9E7kf6w2mNunFpD7drxyNgHLw+XwIYAgb+Xt16SEXo0Up4VH+TMf3n+DSVJZtW2POBGcBYAA==", "integrity": "sha512-kz18NW79x0IHbxRSHm0jttP4zoO9P9gXh+n6UTwlNKnviTTEpOlum6oS9SmecrTtSr+muHEn5TUuC75UovQzcA==",
"dev": true, "dev": true,
"license": "MIT",
"dependencies": { "dependencies": {
"picocolors": "^1.0.0", "picocolors": "^1.0.0",
"picomatch": "^2.3.1" "picomatch": "^2.3.1"

View File

@@ -10,13 +10,13 @@
"@vitejs/plugin-vue": "5.2.1", "@vitejs/plugin-vue": "5.2.1",
"autoprefixer": "10.4.20", "autoprefixer": "10.4.20",
"axios": "1.7.9", "axios": "1.7.9",
"laravel-echo": "1.17.1", "laravel-echo": "2.0.2",
"laravel-vite-plugin": "1.1.1", "laravel-vite-plugin": "^1.2.0",
"postcss": "8.4.49", "postcss": "8.5.3",
"pusher-js": "8.4.0-rc2", "pusher-js": "8.4.0",
"tailwind-scrollbar": "^3.1.0", "tailwind-scrollbar": "^3.1.0",
"tailwindcss": "3.4.17", "tailwindcss": "3.4.17",
"vite": "6.0.11", "vite": "^6.1.1",
"vue": "3.5.13" "vue": "3.5.13"
}, },
"dependencies": { "dependencies": {
@@ -24,6 +24,6 @@
"@tailwindcss/typography": "0.5.16", "@tailwindcss/typography": "0.5.16",
"@xterm/addon-fit": "^0.10.0", "@xterm/addon-fit": "^0.10.0",
"@xterm/xterm": "^5.5.0", "@xterm/xterm": "^5.5.0",
"ioredis": "5.4.2" "ioredis": "5.5.0"
} }
} }

1
public/svgs/denoKV.svg Normal file
View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 4410 4410"><circle cx="2200" cy="2200" r="2200" fill="#fff"/><path d="M384 3039a1991 1991 0 0 1-184-839c0-78 4-154 13-229a2007 2007 0 0 1 39-224A2000 2000 0 0 1 871 706a2001 2001 0 0 1 910-462 2004 2004 0 0 1 571-38 1994 1994 0 0 1 680 175 2003 2003 0 0 1 463 295 2004 2004 0 0 1 676 1180 2009 2009 0 0 1 29 344 2025 2025 0 0 1-6 152 1998 1998 0 0 1-121 551 2001 2001 0 0 1-397 646 1035 1035 0 0 1-738 323 722 722 0 0 1-688-910c17-64 62-186 127-240a762 762 0 0 1-205-138c-7-8-6-22 1-31a26 26 0 0 1 29-8 1458 1458 0 0 0 228 58c111 18 248 42 387 48 338 17 692-135 802-437 109-303 67-602-327-781-394-180-576-393-894-522-208-84-439-34-676 98-640 353-1213 1470-949 2505a32 32 0 0 1-52 31 2011 2011 0 0 1-209-272 2003 2003 0 0 1-128-234zm1745-1989c107-8 202 84 218 206 21 163-39 332-235 336-169 3-220-166-208-269 11-103 95-263 224-273z"/></svg>

After

Width:  |  Height:  |  Size: 891 B

150
public/svgs/wakapi.svg Normal file
View File

@@ -0,0 +1,150 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="275.9418mm"
height="107.06042mm"
viewBox="0 0 275.9418 107.06042"
version="1.1"
id="svg900"
inkscape:version="1.0.1 (3bc2e813f5, 2020-09-07)"
sodipodi:docname="logo-dark-bg.svg">
<defs
id="defs894">
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath20">
<path
d="M 0,700 H 1100 V 0 H 0 Z"
id="path18" />
</clipPath>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.35"
inkscape:cx="501.46484"
inkscape:cy="865.17604"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
inkscape:document-rotation="0"
showgrid="false"
inkscape:window-width="1346"
inkscape:window-height="1198"
inkscape:window-x="149"
inkscape:window-y="113"
inkscape:window-maximized="0" />
<metadata
id="metadata897">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(26.845906,80.744493)">
<g
id="g14"
transform="matrix(0.35277777,0,0,-0.35277777,-100.60779,96.696294)">
<g
id="g16"
clip-path="url(#clipPath20)">
<g
id="g22"
transform="translate(600.9092,345.958)" />
<g
id="g26"
transform="translate(706.707,299.5566)" />
<g
id="g30"
transform="translate(810.2764,345.958)" />
<g
id="g34"
transform="translate(930.5527,345.958)" />
<g
id="g40"
transform="translate(503.8398,367.5195)">
<path
d="m 8.7266003,-16.286056 c 0,-3.170064 -0.10674,-6.340128 -0.32021,-9.492657 -0.85541,-13.857403 -3.56194,-27.197135 -7.89009005,-39.789715 C -18.95161,-122.31318 -71.13644,-163.86557 -133.5283,-167.69511 c -3.13424,-0.23101 -6.30506,-0.32097 -9.49342,-0.32097 -3.1876,0 -6.33937,0.09 -9.4919,0.32097 -76.24773,4.68419 -137.23296,65.6679 -141.91639,141.916397 -0.23101,3.152529 -0.32098,6.322593 -0.32098,9.492657 0,3.188361 0.09,6.358425 0.32098,9.493419 4.68343,76.22944 65.66866,137.249737 141.91639,141.933927 3.15253,0.21348 6.3043,0.32098 9.4919,0.32098 3.18836,0 6.35918,-0.1075 9.49342,-0.32098 V 94.354359 h -18.98532 V 110.75818 C -215.22645,106.14489 -265.43361,55.901133 -270.06444,-6.792637 h 14.65793 v -18.986076 h -14.65793 c 4.63083,-62.712067 54.83799,-112.920757 117.55082,-117.551577 v 16.72479 h 18.98532 v -16.72479 c 46.32654,3.42013 85.86619,31.73876 105.20907,71.59937 6.83873,14.070117 11.14859,29.584217 12.34251,45.952207 h -0.0358 l 8.8697703,18.986076 h 15.54917 c 0.21347,-3.134994 0.32021,-6.305058 0.32021,-9.493419"
style="fill:#2f855a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.762401"
id="path42" />
</g>
<g
id="g44"
transform="translate(504.2754,431.2373)">
<path
d="m 11.6231,-31.425333 -17.1029497,8.252992 -4.6666503,-9.703842 -9.61922,-20.006168 -37.98968,-78.855149 -0.0572,-0.0854 h -37.47886 l -0.0282,0.0572 0.0282,0.0854 14.77,30.64853 3.78456,7.85425 0.19898,0.42618 19.2087,39.869009 7.37013,15.25336 2.27653,4.752808 11.72497,24.386926 -5.77672,2.761416 -9.59024,4.638449 49.9708203,23.249422 z"
style="fill:#2f855a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.762401"
id="path46" />
</g>
<g
id="g48"
transform="translate(258.5654,361.2139)">
<path
d="m 65.50352,-19.287853 v -0.0183 L 46.73396,-58.308305 12.56848,12.654468 2.9523203,32.646912 H 40.49066 l 9.63446,-19.992444 z"
style="fill:#2f855a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.762401"
id="path50" />
</g>
<g
id="g52"
transform="translate(320.9248,367.3867)">
<path
d="M 52.18699,-16.254503 27.28545,-67.966647 v -0.01906 h -37.57494 v 0.01906 l 18.7870903,39.002155 19.2506297,39.94677 5.65168,11.764611 5.66921,-11.764611 9.2647,-19.232331 z"
style="fill:#2f855a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.762401"
id="path54" />
</g>
<g
id="g56"
transform="translate(383.7656,359.833)">
<path
d="m 38.75609,-18.959752 -3.78456,-7.854257 -14.7982,-30.591345 -0.0282,-0.08539 -25.2979997,52.560696 -9.1358503,18.95253 -9.61769,20.005406 h 37.10759 z"
style="fill:#2f855a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.762401"
id="path58" />
</g>
</g>
</g>
<g
aria-label="akapi"
transform="matrix(0.35277777,0,0,0.35277777,-84.30991,101.5377)"
id="text856"
style="font-style:normal;font-variant:normal;font-weight:500;font-stretch:normal;font-size:176px;line-height:1.25;font-family:Roboto;-inkscape-font-specification:'Roboto, Medium';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;letter-spacing:7.5px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.75">
<path
d="m 565.57956,-313.41107 q -1.375,-2.66406 -2.40625,-8.67969 -9.96875,10.39844 -24.40625,10.39844 -14.00781,0 -22.85938,-7.99219 -8.85156,-7.99219 -8.85156,-19.76562 0,-14.86719 11,-22.77344 11.08594,-7.99219 31.625,-7.99219 h 12.80469 v -6.10156 q 0,-7.21875 -4.03906,-11.51563 -4.03907,-4.38281 -12.28907,-4.38281 -7.13281,0 -11.6875,3.60938 -4.55468,3.52343 -4.55468,9.02343 h -20.88282 q 0,-7.64843 5.07032,-14.26562 5.07031,-6.70313 13.75,-10.48438 8.76562,-3.78125 19.50781,-3.78125 16.32812,0 26.03906,8.25 9.71094,8.16407 9.96875,23.03125 v 41.9375 q 0,12.54688 3.52344,20.02344 v 1.46094 z m -22.94531,-15.03906 q 6.1875,0 11.60156,-3.00782 5.5,-3.00781 8.25,-8.07812 v -17.53125 H 551.228 q -11.60157,0 -17.44532,4.03906 -5.84375,4.03906 -5.84375,11.42969 0,6.01562 3.95313,9.625 4.03906,3.52344 10.74219,3.52344 z"
style="font-style:normal;font-variant:normal;font-weight:500;font-stretch:normal;font-size:176px;font-family:Roboto;-inkscape-font-specification:'Roboto, Medium';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#ffffff;fill-opacity:1;stroke-width:0.75"
id="path851" />
<path
d="m 642.94675,-353.28607 -9.28125,9.53906 v 30.33594 h -20.88282 v -132 h 20.88282 v 76.14062 l 6.53125,-8.16406 25.69531,-28.96094 h 25.09375 l -34.54688,38.75782 38.24219,54.22656 h -24.14844 z"
style="font-style:normal;font-variant:normal;font-weight:500;font-stretch:normal;font-size:176px;font-family:Roboto;-inkscape-font-specification:'Roboto, Medium';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#ffffff;fill-opacity:1;stroke-width:0.75"
id="path853" />
<path
d="m 767.6655,-313.41107 q -1.375,-2.66406 -2.40625,-8.67969 -9.96875,10.39844 -24.40625,10.39844 -14.00782,0 -22.85938,-7.99219 -8.85156,-7.99219 -8.85156,-19.76562 0,-14.86719 11,-22.77344 11.08594,-7.99219 31.625,-7.99219 h 12.80469 v -6.10156 q 0,-7.21875 -4.03907,-11.51563 -4.03906,-4.38281 -12.28906,-4.38281 -7.13281,0 -11.6875,3.60938 -4.55469,3.52343 -4.55469,9.02343 h -20.88281 q 0,-7.64843 5.07031,-14.26562 5.07032,-6.70313 13.75,-10.48438 8.76563,-3.78125 19.50782,-3.78125 16.32812,0 26.03906,8.25 9.71094,8.16407 9.96875,23.03125 v 41.9375 q 0,12.54688 3.52344,20.02344 v 1.46094 z m -22.94532,-15.03906 q 6.1875,0 11.60157,-3.00782 5.5,-3.00781 8.25,-8.07812 v -17.53125 h -11.25782 q -11.60156,0 -17.44531,4.03906 -5.84375,4.03906 -5.84375,11.42969 0,6.01562 3.95313,9.625 4.03906,3.52344 10.74218,3.52344 z"
style="font-style:normal;font-variant:normal;font-weight:500;font-stretch:normal;font-size:176px;font-family:Roboto;-inkscape-font-specification:'Roboto, Medium';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#ffffff;fill-opacity:1;stroke-width:0.75"
id="path855" />
<path
d="m 896.25143,-358.95795 q 0,21.57032 -9.79687,34.46094 -9.79688,12.80469 -26.29688,12.80469 -15.29687,0 -24.49218,-10.05469 v 44.08594 h -20.88282 v -128.73438 h 19.25 l 0.85938,9.45313 q 9.19531,-11.17188 25.00781,-11.17188 17.01563,0 26.64063,12.71875 9.71093,12.63282 9.71093,35.14844 z m -20.79687,-1.80468 q 0,-13.92188 -5.58594,-22.08594 -5.5,-8.16406 -15.8125,-8.16406 -12.80469,0 -18.39062,10.57031 v 41.25 q 5.67187,10.82812 18.5625,10.82812 9.96875,0 15.55468,-7.99218 5.67188,-8.07813 5.67188,-24.40625 z"
style="font-style:normal;font-variant:normal;font-weight:500;font-stretch:normal;font-size:176px;font-family:Roboto;-inkscape-font-specification:'Roboto, Medium';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#ffffff;fill-opacity:1;stroke-width:0.75"
id="path857" />
<path
d="m 943.62643,-313.41107 h -20.88281 v -92.98438 h 20.88281 z m -22.17187,-117.13281 q 0,-4.8125 3.00781,-7.99219 3.09375,-3.17969 8.76563,-3.17969 5.67187,0 8.76562,3.17969 3.09375,3.17969 3.09375,7.99219 0,4.72656 -3.09375,7.90625 -3.09375,3.09375 -8.76562,3.09375 -5.67188,0 -8.76563,-3.09375 -3.00781,-3.17969 -3.00781,-7.90625 z"
style="font-style:normal;font-variant:normal;font-weight:500;font-stretch:normal;font-size:176px;font-family:Roboto;-inkscape-font-specification:'Roboto, Medium';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#ffffff;fill-opacity:1;stroke-width:0.75"
id="path859" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 10 KiB

View File

@@ -25,11 +25,6 @@ body {
@apply hidden !important; @apply hidden !important;
} }
.input,
.select {
@apply text-black dark:bg-coolgray-100 dark:text-white ring-neutral-200 dark:ring-coolgray-300;
}
.input-sticky { .input-sticky {
@apply text-black dark:bg-coolgray-100 dark:text-white ring-neutral-200 dark:ring-coolgray-300 focus:ring-2 dark:focus:ring-coolgray-300 focus:ring-neutral-400 block w-full py-1.5 rounded border-0 text-sm ring-1 ring-inset; @apply text-black dark:bg-coolgray-100 dark:text-white ring-neutral-200 dark:ring-coolgray-300 focus:ring-2 dark:focus:ring-coolgray-300 focus:ring-neutral-400 block w-full py-1.5 rounded border-0 text-sm ring-1 ring-inset;
} }
@@ -51,7 +46,11 @@ body {
.input, .input,
.select { .select {
@apply block w-full py-1.5 rounded border-0 text-sm ring-1 ring-inset; @apply text-black dark:bg-coolgray-100 dark:text-white ring-neutral-200 dark:ring-coolgray-300 block w-full py-1.5 rounded border-0 text-sm ring-1 ring-inset;
}
.select {
@apply w-full;
} }
.input[type="password"] { .input[type="password"] {

View File

@@ -57,7 +57,8 @@
language: '{{ $language }}', language: '{{ $language }}',
domReadOnly: '{{ $readonly ?? false }}', domReadOnly: '{{ $readonly ?? false }}',
contextmenu: '!{{ $readonly ?? false }}', contextmenu: '!{{ $readonly ?? false }}',
renderLineHighlight: '{{ $readonly ?? false }} ? none : all' renderLineHighlight: '{{ $readonly ?? false }} ? none : all',
stickyScroll: { enabled: false }
}); });
const observer = new MutationObserver((mutations) => { const observer = new MutationObserver((mutations) => {

View File

@@ -2,7 +2,7 @@
<div class="flex flex-col items-center justify-center h-full"> <div class="flex flex-col items-center justify-center h-full">
<div> <div>
<p class="font-mono font-semibold text-7xl dark:text-warning">404</p> <p class="font-mono font-semibold text-7xl dark:text-warning">404</p>
<h1 class="mt-4 font-bold tracking-tight dark:text-white">How did you got here?</h1> <h1 class="mt-4 font-bold tracking-tight dark:text-white">How did you get here?</h1>
<p class="text-base leading-7 text-neutral-300">Sorry, we couldnt find the page youre looking <p class="text-base leading-7 text-neutral-300">Sorry, we couldnt find the page youre looking
for. for.
</p> </p>

View File

@@ -79,6 +79,16 @@
</x-slot:button-text> </x-slot:button-text>
</x-popup> </x-popup>
</span> </span>
@if (currentTeam()->subscriptionPastOverDue())
<x-banner :closable=false>
<div><span class="font-bold text-red-500">WARNING:</span> Your subscription is in over-due. If your latest
payment is not paid within a week, all automations <span class="font-bold text-red-500">will
be deactivated</span>. Visit <a href="{{ route('subscription.show') }}"
class="underline dark:text-white">/subscription</a> to check your subscription status or pay your
invoice (or check your email for the invoice).
</div>
</x-banner>
@endif
@if (currentTeam()->serverOverflow()) @if (currentTeam()->serverOverflow())
<x-banner :closable=false> <x-banner :closable=false>
<div><span class="font-bold text-red-500">WARNING:</span> The number of active servers exceeds the limit <div><span class="font-bold text-red-500">WARNING:</span> The number of active servers exceeds the limit

View File

@@ -58,12 +58,9 @@
<x-forms.checkbox instantSave id="isConnectToDockerNetworkEnabled" label="Connect To Predefined Network" <x-forms.checkbox instantSave id="isConnectToDockerNetworkEnabled" label="Connect To Predefined Network"
helper="By default, you do not reach the Coolify defined networks.<br>Starting a docker compose based resource will have an internal network. <br>If you connect to a Coolify defined network, you maybe need to use different internal DNS names to connect to a resource.<br><br>For more information, check <a class='underline dark:text-white' target='_blank' href='https://coolify.io/docs/knowledge-base/docker/compose#connect-to-predefined-networks'>this</a>." /> helper="By default, you do not reach the Coolify defined networks.<br>Starting a docker compose based resource will have an internal network. <br>If you connect to a Coolify defined network, you maybe need to use different internal DNS names to connect to a resource.<br><br>For more information, check <a class='underline dark:text-white' target='_blank' href='https://coolify.io/docs/knowledge-base/docker/compose#connect-to-predefined-networks'>this</a>." />
@endif @endif
@if ($isLogDrainEnabled === false) <h3 class="pt-4">Logs</h3>
<h3 class="pt-4">Logs</h3> <x-forms.checkbox helper="Drain logs to your configured log drain endpoint in your Server settings."
<x-forms.checkbox helper="Drain logs to your configured log drain endpoint in your Server settings." instantSave id="isLogDrainEnabled" label="Drain Logs" />
instantSave id="isLogDrainEnabled" label="Drain Logs" />
@endif
@if ($application->git_based()) @if ($application->git_based())
<h3>Git</h3> <h3>Git</h3>
<x-forms.checkbox instantSave id="isGitSubmodulesEnabled" label="Submodules" <x-forms.checkbox instantSave id="isGitSubmodulesEnabled" label="Submodules"

View File

@@ -15,9 +15,9 @@
</div> </div>
<div class="pb-4">Deploy any public or private Git repositories through a GitHub App.</div> <div class="pb-4">Deploy any public or private Git repositories through a GitHub App.</div>
@if ($github_apps->count() !== 0) @if ($github_apps->count() !== 0)
<h2 class="pt-4 pb-4">Select a Github App</h2>
<div class="flex flex-col gap-2"> <div class="flex flex-col gap-2">
@if ($current_step === 'github_apps') @if ($current_step === 'github_apps')
<h2 class="pt-4 pb-4">Select a Github App</h2>
<div class="flex flex-col justify-center gap-2 text-left"> <div class="flex flex-col justify-center gap-2 text-left">
@foreach ($github_apps as $ghapp) @foreach ($github_apps as $ghapp)
<div class="flex"> <div class="flex">
@@ -43,25 +43,28 @@
@endif @endif
@if ($current_step === 'repository') @if ($current_step === 'repository')
@if ($repositories->count() > 0) @if ($repositories->count() > 0)
<div class="flex items-end gap-2"> <div class="flex flex-col gap-2 pb-6">
<x-forms.select class="w-full" label="Repository" wire:model="selected_repository_id"> <div class="flex gap-2">
@foreach ($repositories as $repo) <x-forms.select class="w-full" label="Repository" wire:model="selected_repository_id">
@if ($loop->first) @foreach ($repositories as $repo)
<option selected value="{{ data_get($repo, 'id') }}"> @if ($loop->first)
{{ data_get($repo, 'name') }} <option selected value="{{ data_get($repo, 'id') }}">
</option> {{ data_get($repo, 'name') }}
@else </option>
<option value="{{ data_get($repo, 'id') }}">{{ data_get($repo, 'name') }} @else
</option> <option value="{{ data_get($repo, 'id') }}">{{ data_get($repo, 'name') }}
@endif </option>
@endforeach @endif
</x-forms.select> @endforeach
</x-forms.select>
</div>
<x-forms.button wire:click.prevent="loadBranches"> Load Repository </x-forms.button> <x-forms.button wire:click.prevent="loadBranches"> Load Repository </x-forms.button>
</div> </div>
@else @else
<div>No repositories found. Check your GitHub App configuration.</div> <div>No repositories found. Check your GitHub App configuration.</div>
@endif @endif
@if ($branches->count() > 0) @if ($branches->count() > 0)
<h2 class="text-lg font-bold">Configuration</h2>
<div class="flex flex-col gap-2 pb-6"> <div class="flex flex-col gap-2 pb-6">
<form class="flex flex-col" wire:submit='submit'> <form class="flex flex-col" wire:submit='submit'>
<div class="flex flex-col gap-2 pb-6"> <div class="flex flex-col gap-2 pb-6">

View File

@@ -176,7 +176,9 @@
</div> </div>
<div class="pb-4">Persistent storage to preserve data between deployments.</div> <div class="pb-4">Persistent storage to preserve data between deployments.</div>
<div class="pb-4 dark:text-warning text-coollabs">If you would like to add a volume, you must add it to <div class="pb-4 dark:text-warning text-coollabs">If you would like to add a volume, you must add it to
your compose file (Service Stack tab).</div> your compose file (<a class="underline"
href="{{ route('project.service.configuration', ['project_uuid' => $project->uuid, 'environment_uuid' => $environment->uuid, 'service_uuid' => $service->uuid]) }}"
wire:navigate>General tab</a>).</div>
@foreach ($applications as $application) @foreach ($applications as $application)
<livewire:project.service.storage wire:key="application-{{ $application->id }}" <livewire:project.service.storage wire:key="application-{{ $application->id }}"
:resource="$application" /> :resource="$application" />

View File

@@ -1,35 +1,48 @@
<div x-data="{ raw: true }"> <div x-data="{ raw: true, showNormalTextarea: false }">
<div class="pb-4">Volume names are updated upon save. The service UUID will be added as a prefix to all volumes, to <div class="pb-4">Volume names are updated upon save. The service UUID will be added as a prefix to all volumes, to
prevent prevent
name collision. <br>To see the actual volume names, check the Deployable Compose file, or go to Storage name collision. <br>To see the actual volume names, check the Deployable Compose file, or go to Storage
menu.</div> menu.</div>
<div x-cloak x-show="raw" class="font-mono"> <div x-cloak x-show="raw" class="font-mono">
<x-forms.textarea allowTab useMonacoEditor monacoEditorLanguage="yaml" rows="20" <div x-cloak x-show="showNormalTextarea">
id="service.docker_compose_raw"> <x-forms.textarea rows="20" id="service.docker_compose_raw">
</x-forms.textarea> </x-forms.textarea>
</div>
<div x-cloak x-show="!showNormalTextarea">
<x-forms.textarea allowTab useMonacoEditor monacoEditorLanguage="yaml" rows="20"
id="service.docker_compose_raw">
</x-forms.textarea>
</div>
</div> </div>
<div x-cloak x-show="raw === false" class="font-mono"> <div x-cloak x-show="raw === false" class="font-mono">
<x-forms.textarea rows="20" readonly id="service.docker_compose"> <x-forms.textarea rows="20" readonly id="service.docker_compose">
</x-forms.textarea> </x-forms.textarea>
</div> </div>
<div class="pt-2 w-96"> <div class="pt-2 flex gap-2">
<x-forms.checkbox label="Escape special characters in labels?" <div class="flex flex-col gap-2">
helper="By default, $ (and other chars) is escaped. So if you write $ in the labels, it will be saved as $$.<br><br>If you want to use env variables inside the labels, turn this off." <x-forms.checkbox label="Escape special characters in labels?"
id="service.is_container_label_escape_enabled" instantSave></x-forms.checkbox> helper="By default, $ (and other chars) is escaped. So if you write $ in the labels, it will be saved as $$.<br><br>If you want to use env variables inside the labels, turn this off."
id="service.is_container_label_escape_enabled" instantSave></x-forms.checkbox>
<x-forms.checkbox label="Show Normal Textarea" x-model="showNormalTextarea"></x-forms.checkbox>
</div>
</div> </div>
<div class="flex justify-end w-full gap-2 pt-4"> <div class="flex w-full gap-2 pt-4">
<div class="flex items-end gap-2"> <div x-cloak x-show="raw">
<div x-cloak x-show="raw"> <x-forms.button class="w-64" @click.prevent="raw = !raw">Show Deployable Compose</x-forms.button>
<x-forms.button class="w-64" @click.prevent="raw = !raw">Show Deployable Compose</x-forms.button> </div>
</div> <div x-cloak x-show="raw === false">
<div x-cloak x-show="raw === false"> <x-forms.button class="w-64" @click.prevent="raw = !raw">Show Source
<x-forms.button class="w-64" @click.prevent="raw = !raw">Show Source Compose</x-forms.button>
Compose</x-forms.button>
</div>
</div> </div>
<div class="flex-1"></div> <div class="flex-1"></div>
<x-forms.button class="w-64" wire:click.prevent='saveEditedCompose'> @if (blank($service->service_type))
<x-forms.button class="w-28" wire:click.prevent='validateCompose'>
Validate
</x-forms.button>
@endif
<x-forms.button class="w-28" wire:click.prevent='saveEditedCompose'>
Save Save
</x-forms.button> </x-forms.button>
</div> </div>

View File

@@ -21,15 +21,6 @@
]" confirmationText="{{ $fs_path }}" ]" confirmationText="{{ $fs_path }}"
confirmationLabel="Please confirm the execution of the actions by entering the Filepath below" confirmationLabel="Please confirm the execution of the actions by entering the Filepath below"
shortConfirmationLabel="Filepath" :confirmWithPassword="false" step2ButtonText="Convert to file" /> shortConfirmationLabel="Filepath" :confirmWithPassword="false" step2ButtonText="Convert to file" />
@else
<x-modal-confirmation title="Confirm File Conversion to Directory?" buttonTitle="Convert to directory"
submitAction="convertToDirectory" :actions="[
'The selected file will be permanently deleted and an empty directory will be created in its place.',
]" confirmationText="{{ $fs_path }}"
confirmationLabel="Please confirm the execution of the actions by entering the Filepath below"
shortConfirmationLabel="Filepath" :confirmWithPassword="false" step2ButtonText="Convert to directory" />
@endif
@if ($fileStorage->is_directory)
<x-modal-confirmation title="Confirm Directory Deletion?" buttonTitle="Delete Directory" isErrorButton <x-modal-confirmation title="Confirm Directory Deletion?" buttonTitle="Delete Directory" isErrorButton
submitAction="delete" :checkboxes="$directoryDeletionCheckboxes" :actions="[ submitAction="delete" :checkboxes="$directoryDeletionCheckboxes" :actions="[
'The selected directory and all its contents will be permanently deleted from the container.', 'The selected directory and all its contents will be permanently deleted from the container.',
@@ -37,13 +28,18 @@
confirmationLabel="Please confirm the execution of the actions by entering the Filepath below" confirmationLabel="Please confirm the execution of the actions by entering the Filepath below"
shortConfirmationLabel="Filepath" step3ButtonText="Permanently Delete" /> shortConfirmationLabel="Filepath" step3ButtonText="Permanently Delete" />
@else @else
<x-modal-confirmation title="Confirm File Conversion to Directory?" buttonTitle="Convert to directory"
submitAction="convertToDirectory" :actions="[
'The selected file will be permanently deleted and an empty directory will be created in its place.',
]" confirmationText="{{ $fs_path }}"
confirmationLabel="Please confirm the execution of the actions by entering the Filepath below"
shortConfirmationLabel="Filepath" :confirmWithPassword="false" step2ButtonText="Convert to directory" />
<x-modal-confirmation title="Confirm File Deletion?" buttonTitle="Delete File" isErrorButton <x-modal-confirmation title="Confirm File Deletion?" buttonTitle="Delete File" isErrorButton
submitAction="delete" :checkboxes="$fileDeletionCheckboxes" :actions="['The selected file will be permanently deleted from the container.']" confirmationText="{{ $fs_path }}" submitAction="delete" :checkboxes="$fileDeletionCheckboxes" :actions="['The selected file will be permanently deleted from the container.']" confirmationText="{{ $fs_path }}"
confirmationLabel="Please confirm the execution of the actions by entering the Filepath below" confirmationLabel="Please confirm the execution of the actions by entering the Filepath below"
shortConfirmationLabel="Filepath" step3ButtonText="Permanently Delete" /> shortConfirmationLabel="Filepath" step3ButtonText="Permanently Delete" />
@endif @endif
{{-- @if (!$fileStorage->is_based_on_git)
@if (!$fileStorage->is_based_on_git)
<x-modal-confirmation isErrorButton buttonTitle="Delete"> <x-modal-confirmation isErrorButton buttonTitle="Delete">
<div class="px-2">This storage will be deleted. It is not reversible. <strong <div class="px-2">This storage will be deleted. It is not reversible. <strong
class="text-error">Please class="text-error">Please
@@ -58,7 +54,7 @@
label="Permanently delete file from the server?"></x-forms.checkbox> label="Permanently delete file from the server?"></x-forms.checkbox>
@endif @endif
</x-modal-confirmation> </x-modal-confirmation>
@endif @endif --}}
</div> </div>
@if (!$fileStorage->is_directory) @if (!$fileStorage->is_directory)
@if (data_get($resource, 'settings.is_preserve_repository_enabled')) @if (data_get($resource, 'settings.is_preserve_repository_enabled'))
@@ -75,6 +71,5 @@
<x-forms.button class="w-full" type="submit">Save</x-forms.button> <x-forms.button class="w-full" type="submit">Save</x-forms.button>
@endif @endif
@endif @endif
</form> </form>
</div> </div>

View File

@@ -47,6 +47,10 @@
<x-forms.checkbox instantSave id="is_build_time" <x-forms.checkbox instantSave id="is_build_time"
helper="If you are using Docker, remember to modify the file to be ready to receive the build time args. Ex.: for docker file, add `ARG name_of_the_variable`, or dockercompose add `- 'name_of_the_variable=${name_of_the_variable}'`" helper="If you are using Docker, remember to modify the file to be ready to receive the build time args. Ex.: for docker file, add `ARG name_of_the_variable`, or dockercompose add `- 'name_of_the_variable=${name_of_the_variable}'`"
label="Build Variable?" /> label="Build Variable?" />
<x-forms.checkbox instantSave id="is_literal"
helper="This means that when you use $VARIABLES in a value, it should be interpreted as the actual characters '$VARIABLES' and not as the value of a variable named VARIABLE.<br><br>Useful if you have $ sign in your value and there are some characters after it, but you would not like to interpolate it from another value. In this case, you should set this to true."
label="Is Literal?" />
<x-forms.checkbox instantSave id="is_multiline" label="Is Multiline?" />
@else @else
@if ($is_shared) @if ($is_shared)
<x-forms.checkbox instantSave id="is_build_time" <x-forms.checkbox instantSave id="is_build_time"

View File

@@ -3,9 +3,9 @@
<h2>Scheduled Tasks</h2> <h2>Scheduled Tasks</h2>
<x-modal-input buttonTitle="+ Add" title="New Scheduled Task" :closeOutside="false"> <x-modal-input buttonTitle="+ Add" title="New Scheduled Task" :closeOutside="false">
@if ($resource->type() == 'application') @if ($resource->type() == 'application')
<livewire:project.shared.scheduled-task.add :type="$resource->type()" :containerNames="$containerNames" /> <livewire:project.shared.scheduled-task.add :type="$resource->type()" :id="$resource->id" :containerNames="$containerNames" />
@elseif ($resource->type() == 'service') @elseif ($resource->type() == 'service')
<livewire:project.shared.scheduled-task.add :type="$resource->type()" :containerNames="$containerNames" /> <livewire:project.shared.scheduled-task.add :type="$resource->type()" :id="$resource->id" :containerNames="$containerNames" />
@endif @endif
</x-modal-input> </x-modal-input>
</div> </div>

View File

@@ -134,7 +134,14 @@
<div class="w-full"> <div class="w-full">
@if (!$server->isLocalhost()) @if (!$server->isLocalhost())
<div class="w-96"> <div class="w-96">
<x-forms.checkbox instantSave id="isBuildServer" label="Use it as a build server?" /> @if ($isBuildServerLocked)
<x-forms.checkbox disabled instantSave id="isBuildServer"
helper="You can't use this server as a build server because it has defined resources."
label="Use it as a build server?" />
@else
<x-forms.checkbox instantSave id="isBuildServer"
label="Use it as a build server?" />
@endif
</div> </div>
@if (!$server->isBuildServer() && !$server->settings->is_cloudflare_tunnel) @if (!$server->isBuildServer() && !$server->settings->is_cloudflare_tunnel)

View File

@@ -32,6 +32,11 @@
<x-forms.input id="oauth_settings_map.{{ $oauth_setting->provider }}.tenant" <x-forms.input id="oauth_settings_map.{{ $oauth_setting->provider }}.tenant"
label="Tenant" /> label="Tenant" />
@endif @endif
@if ($oauth_setting->provider == 'google')
<x-forms.input id="oauth_settings_map.{{ $oauth_setting->provider }}.tenant"
helper="Optional parameter that supplies a hosted domain (HD) to Google, which<br>triggers a login hint to be displayed on the OAuth screen with this domain.<br><br><a class='underline dark:text-warning text-coollabs' href='https://developers.google.com/identity/openid-connect/openid-connect#hd-param' target='_blank'>Google Documentation</a>"
label="Tenant" />
@endif
@if ($oauth_setting->provider == 'authentik') @if ($oauth_setting->provider == 'authentik')
<x-forms.input id="oauth_settings_map.{{ $oauth_setting->provider }}.base_url" <x-forms.input id="oauth_settings_map.{{ $oauth_setting->provider }}.base_url"
label="Base URL" /> label="Base URL" />

View File

@@ -132,12 +132,12 @@
<h4 class="py-4">Confirmation Settings</h4> <h4 class="py-4">Confirmation Settings</h4>
@if ($disable_two_step_confirmation) @if ($disable_two_step_confirmation)
<div class="md:w-96 pb-4"> <div class="md:w-96 pb-4" wire:key="two-step-confirmation-enabled">
<x-forms.checkbox instantSave id="disable_two_step_confirmation" label="Disable Two Step Confirmation" <x-forms.checkbox instantSave id="disable_two_step_confirmation" label="Disable Two Step Confirmation"
helper="When disabled, you will not need to confirm actions with a text and user password. This significantly reduces security and may lead to accidental deletions or unwanted changes. Use with extreme caution, especially on production servers." /> helper="When disabled, you will not need to confirm actions with a text and user password. This significantly reduces security and may lead to accidental deletions or unwanted changes. Use with extreme caution, especially on production servers." />
</div> </div>
@else @else
<div class="md:w-96 pb-4"> <div class="md:w-96 pb-4" wire:key="two-step-confirmation-disabled">
<x-modal-confirmation title="Disable Two Step Confirmation?" <x-modal-confirmation title="Disable Two Step Confirmation?"
buttonTitle="Disable Two Step Confirmation" isErrorButton submitAction="toggleTwoStepConfirmation" buttonTitle="Disable Two Step Confirmation" isErrorButton submitAction="toggleTwoStepConfirmation"
:actions="[ :actions="[

View File

@@ -27,6 +27,7 @@
confirmationText="{{ data_get($github_app, 'name') }}" :confirmWithPassword="false" confirmationText="{{ data_get($github_app, 'name') }}" :confirmWithPassword="false"
step2ButtonText="Permanently Delete" /> step2ButtonText="Permanently Delete" />
@endif @endif
</div> </div>
</div> </div>
<div class="subtitle">Your Private GitHub App for private repositories.</div> <div class="subtitle">Your Private GitHub App for private repositories.</div>
@@ -46,7 +47,7 @@
<div class="flex flex-col gap-2"> <div class="flex flex-col gap-2">
<div class="flex gap-2"> <div class="flex gap-2">
<div class="flex items-end gap-2 w-full"> <div class="flex items-end gap-2 w-full">
<x-forms.input id="github_app.name" label="App Name" disabled /> <x-forms.input id="github_app.name" label="App Name" />
<x-forms.button wire:click.prevent="updateGithubAppName" class="bg-coollabs"> <x-forms.button wire:click.prevent="updateGithubAppName" class="bg-coollabs">
Sync Name Sync Name
</x-forms.button> </x-forms.button>
@@ -57,7 +58,7 @@
</x-forms.button> </x-forms.button>
</a> </a>
</div> </div>
<x-forms.input id="github_app.organization" label="Organization" disabled <x-forms.input id="github_app.organization" label="Organization"
placeholder="If empty, personal user will be used" /> placeholder="If empty, personal user will be used" />
</div> </div>
@if (!isCloud()) @if (!isCloud())
@@ -68,27 +69,32 @@
</div> </div>
@endif @endif
<div class="flex gap-2"> <div class="flex gap-2">
<x-forms.input id="github_app.html_url" label="HTML Url" disabled /> <x-forms.input id="github_app.html_url" label="HTML Url" />
<x-forms.input id="github_app.api_url" label="API Url" disabled /> <x-forms.input id="github_app.api_url" label="API Url" />
</div> </div>
<div class="flex gap-2"> <div class="flex gap-2">
@if ($github_app->html_url === 'https://github.com') <x-forms.input id="github_app.custom_user" label="User" required />
<x-forms.input id="github_app.custom_user" label="User" disabled /> <x-forms.input type="number" id="github_app.custom_port" label="Port" required />
<x-forms.input type="number" id="github_app.custom_port" label="Port" disabled />
@else
<x-forms.input id="github_app.custom_user" label="User" required />
<x-forms.input type="number" id="github_app.custom_port" label="Port" required />
@endif
</div> </div>
<div class="flex gap-2"> <div class="flex gap-2">
<x-forms.input type="number" id="github_app.app_id" label="App Id" disabled /> <x-forms.input type="number" id="github_app.app_id" label="App Id" required />
<x-forms.input type="number" id="github_app.installation_id" label="Installation Id" <x-forms.input type="number" id="github_app.installation_id" label="Installation Id"
disabled /> required />
</div> </div>
<div class="flex gap-2"> <div class="flex gap-2">
<x-forms.input id="github_app.client_id" label="Client Id" type="password" disabled /> <x-forms.input id="github_app.client_id" label="Client Id" type="password" required />
<x-forms.input id="github_app.client_secret" label="Client Secret" type="password" /> <x-forms.input id="github_app.client_secret" label="Client Secret" type="password" required />
<x-forms.input id="github_app.webhook_secret" label="Webhook Secret" type="password" /> <x-forms.input id="github_app.webhook_secret" label="Webhook Secret" type="password" required />
</div>
<div class="flex gap-2">
<x-forms.select id="github_app.private_key_id" label="Private Key" required>
@if (blank($github_app->private_key_id))
<option value="0" selected>Select a private key</option>
@endif
@foreach ($privateKeys as $privateKey)
<option value="{{ $privateKey->id }}">{{ $privateKey->name }}</option>
@endforeach
</x-forms.select>
</div> </div>
<div class="flex items-end gap-2 "> <div class="flex items-end gap-2 ">
<h2 class="pt-4">Permissions</h2> <h2 class="pt-4">Permissions</h2>
@@ -182,120 +188,129 @@
shortConfirmationLabel="GitHub App Name" :confirmWithPassword="false" step2ButtonText="Permanently Delete" /> shortConfirmationLabel="GitHub App Name" :confirmWithPassword="false" step2ButtonText="Permanently Delete" />
</div> </div>
</div> </div>
<div class=" pb-5 rounded alert-error"> <div class="flex flex-col gap-2">
<svg xmlns="http://www.w3.org/2000/svg" class="w-6 h-6 stroke-current shrink-0" fill="none" <h3>Manual Installation</h3>
viewBox="0 0 24 24"> <div class="flex gap-2 items-center">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" If you want to fill the form manually, you can continue below. Only for advanced users.
d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" /> <x-forms.button wire:click.prevent="createGithubAppManually">
</svg> Continue
<span>You must complete this step before you can use this source!</span> </x-forms.button>
</div> </div>
<div class="flex flex-col"> <h3>Automated Installation</h3>
<div class="pb-10"> <div class=" pb-5 rounded alert-error">
@if (!isCloud() || isDev()) <svg xmlns="http://www.w3.org/2000/svg" class="w-6 h-6 stroke-current shrink-0" fill="none"
<div class="flex items-end gap-2"> viewBox="0 0 24 24">
<x-forms.select wire:model.live='webhook_endpoint' label="Webhook Endpoint" <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
helper="All Git webhooks will be sent to this endpoint. <br><br>If you would like to use domain instead of IP address, set your Coolify instance's FQDN in the Settings menu."> d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" />
@if ($ipv4) </svg>
<option value="{{ $ipv4 }}">Use {{ $ipv4 }}</option> <span>You must complete this step before you can use this source!</span>
@endif </div>
@if ($ipv6) <div class="flex flex-col">
<option value="{{ $ipv6 }}">Use {{ $ipv6 }}</option> <div class="pb-10">
@endif @if (!isCloud() || isDev())
@if ($fqdn) <div class="flex items-end gap-2">
<option value="{{ $fqdn }}">Use {{ $fqdn }}</option> <x-forms.select wire:model.live='webhook_endpoint' label="Webhook Endpoint"
@endif helper="All Git webhooks will be sent to this endpoint. <br><br>If you would like to use domain instead of IP address, set your Coolify instance's FQDN in the Settings menu.">
@if (config('app.url')) @if ($ipv4)
<option value="{{ config('app.url') }}">Use {{ config('app.url') }}</option> <option value="{{ $ipv4 }}">Use {{ $ipv4 }}</option>
@endif @endif
</x-forms.select> @if ($ipv6)
<x-forms.button isHighlighted <option value="{{ $ipv6 }}">Use {{ $ipv6 }}</option>
x-on:click.prevent="createGithubApp('{{ $webhook_endpoint }}','{{ $preview_deployment_permissions }}',{{ $administration }})"> @endif
Register Now @if ($fqdn)
</x-forms.button> <option value="{{ $fqdn }}">Use {{ $fqdn }}</option>
</div> @endif
@else @if (config('app.url'))
<div class="flex gap-2"> <option value="{{ config('app.url') }}">Use {{ config('app.url') }}</option>
<h2>Register a GitHub App</h2> @endif
<x-forms.button isHighlighted </x-forms.select>
x-on:click.prevent="createGithubApp('{{ $webhook_endpoint }}','{{ $preview_deployment_permissions }}',{{ $administration }})"> <x-forms.button isHighlighted
Register Now x-on:click.prevent="createGithubApp('{{ $webhook_endpoint }}','{{ $preview_deployment_permissions }}',{{ $administration }})">
</x-forms.button> Register Now
</div> </x-forms.button>
<div>You need to register a GitHub App before using this source.</div> </div>
@endif @else
<div class="flex gap-2">
<h2>Register a GitHub App</h2>
<x-forms.button isHighlighted
x-on:click.prevent="createGithubApp('{{ $webhook_endpoint }}','{{ $preview_deployment_permissions }}',{{ $administration }})">
Register Now
</x-forms.button>
</div>
<div>You need to register a GitHub App before using this source.</div>
@endif
<div class="flex flex-col gap-2 pt-4 w-96"> <div class="flex flex-col gap-2 pt-4 w-96">
<x-forms.checkbox disabled instantSave id="default_permissions" label="Mandatory" <x-forms.checkbox disabled instantSave id="default_permissions" label="Mandatory"
helper="Contents: read<br>Metadata: read<br>Email: read" /> helper="Contents: read<br>Metadata: read<br>Email: read" />
<x-forms.checkbox instantSave id="preview_deployment_permissions" label="Preview Deployments " <x-forms.checkbox instantSave id="preview_deployment_permissions" label="Preview Deployments "
helper="Necessary for updating pull requests with useful comments (deployment status, links, etc.)<br><br>Pull Request: read & write" /> helper="Necessary for updating pull requests with useful comments (deployment status, links, etc.)<br><br>Pull Request: read & write" />
{{-- <x-forms.checkbox instantSave id="administration" label="Administration (for Github Runners)" {{-- <x-forms.checkbox instantSave id="administration" label="Administration (for Github Runners)"
helper="Necessary for adding Github Runners to repositories.<br><br>Administration: read & write" /> --}} helper="Necessary for adding Github Runners to repositories.<br><br>Administration: read & write" /> --}}
</div>
</div> </div>
</div> </div>
</div> <script>
<script> function createGithubApp(webhook_endpoint, preview_deployment_permissions, administration) {
function createGithubApp(webhook_endpoint, preview_deployment_permissions, administration) { const {
const { organization,
organization, uuid,
uuid, html_url
html_url } = @json($github_app);
} = @json($github_app); if (!webhook_endpoint) {
if (!webhook_endpoint) { alert('Please select a webhook endpoint.');
alert('Please select a webhook endpoint.'); return;
return; }
let baseUrl = webhook_endpoint;
const name = @js($name);
const isDev = @js(config('app.env')) ===
'local';
const devWebhook = @js(config('constants.webhooks.dev_webhook'));
if (isDev && devWebhook) {
baseUrl = devWebhook;
}
const webhookBaseUrl = `${baseUrl}/webhooks`;
const path = organization ? `organizations/${organization}/settings/apps/new` : 'settings/apps/new';
const default_permissions = {
contents: 'read',
metadata: 'read',
emails: 'read',
administration: 'read'
};
if (preview_deployment_permissions) {
default_permissions.pull_requests = 'write';
}
if (administration) {
default_permissions.administration = 'write';
}
const data = {
name,
url: baseUrl,
hook_attributes: {
url: `${webhookBaseUrl}/source/github/events`,
active: true,
},
redirect_url: `${webhookBaseUrl}/source/github/redirect`,
callback_urls: [`${baseUrl}/login/github/app`],
public: false,
request_oauth_on_install: false,
setup_url: `${webhookBaseUrl}/source/github/install?source=${uuid}`,
setup_on_update: true,
default_permissions,
default_events: ['pull_request', 'push']
};
const form = document.createElement('form');
form.setAttribute('method', 'post');
form.setAttribute('action', `${html_url}/${path}?state=${uuid}`);
const input = document.createElement('input');
input.setAttribute('id', 'manifest');
input.setAttribute('name', 'manifest');
input.setAttribute('type', 'hidden');
input.setAttribute('value', JSON.stringify(data));
form.appendChild(input);
document.getElementsByTagName('body')[0].appendChild(form);
form.submit();
} }
let baseUrl = webhook_endpoint; </script>
const name = @js($name);
const isDev = @js(config('app.env')) ===
'local';
const devWebhook = @js(config('constants.webhooks.dev_webhook'));
if (isDev && devWebhook) {
baseUrl = devWebhook;
}
const webhookBaseUrl = `${baseUrl}/webhooks`;
const path = organization ? `organizations/${organization}/settings/apps/new` : 'settings/apps/new';
const default_permissions = {
contents: 'read',
metadata: 'read',
emails: 'read',
administration: 'read'
};
if (preview_deployment_permissions) {
default_permissions.pull_requests = 'write';
}
if (administration) {
default_permissions.administration = 'write';
}
const data = {
name,
url: baseUrl,
hook_attributes: {
url: `${webhookBaseUrl}/source/github/events`,
active: true,
},
redirect_url: `${webhookBaseUrl}/source/github/redirect`,
callback_urls: [`${baseUrl}/login/github/app`],
public: false,
request_oauth_on_install: false,
setup_url: `${webhookBaseUrl}/source/github/install?source=${uuid}`,
setup_on_update: true,
default_permissions,
default_events: ['pull_request', 'push']
};
const form = document.createElement('form');
form.setAttribute('method', 'post');
form.setAttribute('action', `${html_url}/${path}?state=${uuid}`);
const input = document.createElement('input');
input.setAttribute('id', 'manifest');
input.setAttribute('name', 'manifest');
input.setAttribute('type', 'hidden');
input.setAttribute('value', JSON.stringify(data));
form.appendChild(input);
document.getElementsByTagName('body')[0].appendChild(form);
form.submit();
}
</script>
@endif @endif
</div> </div>

View File

@@ -336,13 +336,13 @@ if ! [ -x "$(command -v docker)" ]; then
exit 1 exit 1
fi fi
;; ;;
"fedora") "centos" | "fedora" | "rhel")
if [ -x "$(command -v dnf5)" ]; then if [ -x "$(command -v dnf5)" ]; then
# dnf5 is available # dnf5 is available
dnf config-manager addrepo --from-repofile=https://download.docker.com/linux/fedora/docker-ce.repo --overwrite >/dev/null 2>&1 dnf config-manager addrepo --from-repofile=https://download.docker.com/linux/$OS_TYPE/docker-ce.repo --overwrite >/dev/null 2>&1
else else
# dnf5 is not available, use dnf # dnf5 is not available, use dnf
dnf config-manager --add-repo=https://download.docker.com/linux/fedora/docker-ce.repo >/dev/null 2>&1 dnf config-manager --add-repo=https://download.docker.com/linux/$OS_TYPE/docker-ce.repo >/dev/null 2>&1
fi fi
dnf install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin >/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 if ! [ -x "$(command -v docker)" ]; then

View File

@@ -6,7 +6,7 @@
services: services:
authentik-server: authentik-server:
image: ghcr.io/goauthentik/server:${AUTHENTIK_TAG:-2024.12.2} image: ghcr.io/goauthentik/server:${AUTHENTIK_TAG:-2025.2.0}
restart: unless-stopped restart: unless-stopped
command: server command: server
environment: environment:
@@ -35,7 +35,7 @@ services:
redis: redis:
condition: service_healthy condition: service_healthy
authentik-worker: authentik-worker:
image: ghcr.io/goauthentik/server:${AUTHENTIK_TAG:-2024.12.2} image: ghcr.io/goauthentik/server:${AUTHENTIK_TAG:-2025.2.0}
restart: unless-stopped restart: unless-stopped
command: worker command: worker
environment: environment:

View File

@@ -0,0 +1,25 @@
# documentation: https://docs.deno.com/deploy/kv/manual/
# slogan: The Denoland key-value database
# tags: deno, kv, key-value, database
# logo: svgs/deno.svg
# port: 4512
services:
denokv:
image: ghcr.io/denoland/denokv:latest
environment:
- 'ACCESS_TOKEN=${SERVICE_PASSWORD_DENOKV}'
- SERVICE_FQDN_DENOKV_4512
volumes:
- '${COOLIFY_VOLUME_APP}:/data'
command: '--sqlite-path /data/denokv.sqlite serve --access-token ${SERVICE_PASSWORD_DENOKV}'
healthcheck:
test:
- CMD
- nc
- '-zv'
- 127.0.0.1
- '4512'
interval: 5s
timeout: 5s
retries: 3

View File

@@ -38,7 +38,7 @@ services:
- POSTGRES_PASSWORD=$SERVICE_PASSWORD_POSTGRES - POSTGRES_PASSWORD=$SERVICE_PASSWORD_POSTGRES
- POSTGRES_DB=${POSTGRES_DB:-fider} - POSTGRES_DB=${POSTGRES_DB:-fider}
healthcheck: healthcheck:
test: ["CMD", "pg_isready", "-U", "$SERVICE_USER_POSTGRES"] test: ["CMD-SHELL", "pg_isready -d $${POSTGRES_DB} -U $${POSTGRES_USER}"]
interval: 5s interval: 5s
timeout: 20s timeout: 20s
retries: 10 retries: 10

View File

@@ -39,12 +39,17 @@ services:
- FOUNDRY_MINIFY_STATIC_FILES=${FOUNDRY_MINIFY_STATIC_FILES:-true} - FOUNDRY_MINIFY_STATIC_FILES=${FOUNDRY_MINIFY_STATIC_FILES:-true}
# The world ID to startup at system start. # The world ID to startup at system start.
- FOUNDRY_WORLD=${FOUNDRY_WORLD} - FOUNDRY_WORLD=${FOUNDRY_WORLD}
# Optional telemetry.
- FOUNDRY_TELEMETRY=${FOUNDRY_TELEMETRY:-false} - FOUNDRY_TELEMETRY=${FOUNDRY_TELEMETRY:-false}
# The timezone to use for the server.
- TIMEZONE=${TIMEZONE:-UTC} - TIMEZONE=${TIMEZONE:-UTC}
# Set a path to cache downloads of the Foundry distribution archive and speed up subsequent container startups. # Set a path to cache downloads of the Foundry distribution archive and speed up subsequent container startups.
- CONTAINER_CACHE=/data/container_cache - CONTAINER_CACHE=/data/container_cache
volumes: volumes:
- foundryvtt-data:/data - type: bind
source: ${FOUNDRY_DATA:-/data/foundryvtt}
target: /data
is_directory: true
healthcheck: healthcheck:
test: ["CMD", "curl", "-f", "http://127.0.0.1:30000"] test: ["CMD", "curl", "-f", "http://127.0.0.1:30000"]
timeout: 5s timeout: 5s

View File

@@ -14,6 +14,12 @@ services:
- NODE_ENV=${NODE_ENV:-production} - NODE_ENV=${NODE_ENV:-production}
- ENCRYPTION_KEY=${SERVICE_PASSWORD_ENCRYPTIONKEY} - ENCRYPTION_KEY=${SERVICE_PASSWORD_ENCRYPTIONKEY}
- AUTH_SECRET=${SERVICE_REALBASE64_64_AUTHSECRET} - AUTH_SECRET=${SERVICE_REALBASE64_64_AUTHSECRET}
- SMTP_HOST=${SMTP_HOST}
- SMTP_USERNAME=${SMTP_USERNAME}
- SMTP_PASSWORD=${SMTP_PASSWORD}
- SMTP_PORT=${SMTP_PORT}
- SMTP_FROM_ADDRESS=${SMTP_FROM_ADDRESS}
- SMTP_FROM_NAME=${SMTP_FROM_NAME}
- DB_CONNECTION_URI=postgres://${SERVICE_USER_POSTGRES}:${SERVICE_PASSWORD_POSTGRES}@db:5432/${POSTGRES_DB} - DB_CONNECTION_URI=postgres://${SERVICE_USER_POSTGRES}:${SERVICE_PASSWORD_POSTGRES}@db:5432/${POSTGRES_DB}
- REDIS_URL=redis://redis:6379 - REDIS_URL=redis://redis:6379
healthcheck: healthcheck:
@@ -23,8 +29,8 @@ services:
depends_on: depends_on:
redis: redis:
condition: service_healthy condition: service_healthy
db-migration: db:
condition: service_completed_successfully condition: service_healthy
redis: redis:
image: "redis:7" image: "redis:7"
volumes: volumes:
@@ -53,17 +59,3 @@ services:
interval: 5s interval: 5s
timeout: 10s timeout: 10s
retries: 10 retries: 10
db-migration:
exclude_from_hc: true
image: "infisical/infisical:latest-postgres"
depends_on:
db:
condition: service_healthy
command: "npm run migration:latest"
restart: on-failure
environment:
- POSTGRES_USER=${SERVICE_USER_POSTGRES}
- POSTGRES_PASSWORD=${SERVICE_PASSWORD_POSTGRES}
- POSTGRES_DB=${POSTGRES_DB:-infisical}
- DB_CONNECTION_URI=postgres://${SERVICE_USER_POSTGRES}:${SERVICE_PASSWORD_POSTGRES}@db:5432/${POSTGRES_DB:-infisical}
- REDIS_URL=redis://redis:6379

View File

@@ -1,4 +1,4 @@
# documentation: https://owncloud.com/docs # documentation: https://owncloud.com/docs-guides/
# slogan: OwnCloud with Open Web UI integrates file management with a powerful, user-friendly interface. # slogan: OwnCloud with Open Web UI integrates file management with a powerful, user-friendly interface.
# tags: owncloud,file-management,open-web-ui,integration,cloud # tags: owncloud,file-management,open-web-ui,integration,cloud
# logo: svgs/owncloud.svg # logo: svgs/owncloud.svg

View File

@@ -2,7 +2,7 @@
# slogan: Penpot is the first Open Source design and prototyping platform for product teams. # slogan: Penpot is the first Open Source design and prototyping platform for product teams.
# tags: penpot,design,prototyping,figma,open,source # tags: penpot,design,prototyping,figma,open,source
# logo: svgs/penpot.svg # logo: svgs/penpot.svg
# port: 80 # port: 8080
services: services:
frontend: frontend:
@@ -15,10 +15,10 @@ services:
penpot-exporter: penpot-exporter:
condition: service_healthy condition: service_healthy
environment: environment:
- SERVICE_FQDN_FRONTEND - SERVICE_FQDN_FRONTEND_8080
- PENPOT_FLAGS=${PENPOT_FRONTEND_FLAGS:-enable-login-with-password} - PENPOT_FLAGS=${PENPOT_FRONTEND_FLAGS:-enable-login-with-password}
healthcheck: healthcheck:
test: ["CMD", "curl", "-f", "http://127.0.0.1:80"] test: ['CMD', 'curl', '-f', 'http://127.0.0.1:8080']
interval: 2s interval: 2s
timeout: 10s timeout: 10s
retries: 15 retries: 15
@@ -36,7 +36,7 @@ services:
- PENPOT_FLAGS=${PENPOT_BACKEND_FLAGS:-enable-login-with-password enable-smtp enable-prepl-server} - PENPOT_FLAGS=${PENPOT_BACKEND_FLAGS:-enable-login-with-password enable-smtp enable-prepl-server}
- PENPOT_HTTP_SERVER_PORT=6060 - PENPOT_HTTP_SERVER_PORT=6060
- PENPOT_SECRET_KEY=$SERVICE_REALBASE64_64_PENPOT - PENPOT_SECRET_KEY=$SERVICE_REALBASE64_64_PENPOT
- PENPOT_PUBLIC_URI=$SERVICE_FQDN_FRONTEND - PENPOT_PUBLIC_URI=$SERVICE_FQDN_FRONTEND_8080
- PENPOT_BACKEND_URI=http://penpot-backend - PENPOT_BACKEND_URI=http://penpot-backend
- PENPOT_EXPORTER_URI=http://penpot-exporter - PENPOT_EXPORTER_URI=http://penpot-exporter
- PENPOT_DATABASE_URI=postgresql://postgres/${POSTGRES_DB:-penpot} - PENPOT_DATABASE_URI=postgresql://postgres/${POSTGRES_DB:-penpot}
@@ -55,18 +55,18 @@ services:
- PENPOT_SMTP_TLS=${PENPOT_SMTP_TLS:-false} - PENPOT_SMTP_TLS=${PENPOT_SMTP_TLS:-false}
- PENPOT_SMTP_SSL=${PENPOT_SMTP_SSL:-false} - PENPOT_SMTP_SSL=${PENPOT_SMTP_SSL:-false}
healthcheck: healthcheck:
test: ["CMD", "curl", "-f", "http://127.0.0.1:6060/readyz"] test: ['CMD', 'curl', '-f', 'http://127.0.0.1:6060/readyz']
interval: 2s interval: 10s
timeout: 10s timeout: 30s
retries: 15 retries: 15
penpot-exporter: penpot-exporter:
image: penpotapp/exporter:latest image: penpotapp/exporter:latest
environment: environment:
- PENPOT_PUBLIC_URI=$SERVICE_FQDN_FRONTEND - PENPOT_PUBLIC_URI=$SERVICE_FQDN_FRONTEND_8080
- PENPOT_REDIS_URI=redis://redis/0 - PENPOT_REDIS_URI=redis://redis/0
healthcheck: healthcheck:
test: ["CMD", "curl", "-f", "http://127.0.0.1:6061/readyz"] test: ['CMD', 'curl', '-f', 'http://127.0.0.1:6061/readyz']
interval: 2s interval: 2s
timeout: 10s timeout: 10s
retries: 15 retries: 15
@@ -76,7 +76,7 @@ services:
environment: environment:
- SERVICE_FQDN_MAILPIT_8025 - SERVICE_FQDN_MAILPIT_8025
healthcheck: healthcheck:
test: ["CMD", "/mailpit", "readyz"] test: ['CMD', '/mailpit', 'readyz']
interval: 5s interval: 5s
timeout: 20s timeout: 20s
retries: 10 retries: 10
@@ -91,7 +91,7 @@ services:
- POSTGRES_PASSWORD=$SERVICE_PASSWORD_POSTGRES - POSTGRES_PASSWORD=$SERVICE_PASSWORD_POSTGRES
- POSTGRES_DB=${POSTGRES_DB:-penpot} - POSTGRES_DB=${POSTGRES_DB:-penpot}
healthcheck: healthcheck:
test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"] test: ['CMD-SHELL', 'pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}']
interval: 5s interval: 5s
timeout: 20s timeout: 20s
retries: 10 retries: 10
@@ -102,7 +102,7 @@ services:
volumes: volumes:
- penpot-redis-data:/data - penpot-redis-data:/data
healthcheck: healthcheck:
test: ["CMD", "redis-cli", "ping"] test: ['CMD', 'redis-cli', 'ping']
interval: 5s interval: 5s
timeout: 20s timeout: 20s
retries: 10 retries: 10

View File

@@ -5,6 +5,7 @@
x-app-env: &app-env x-app-env: &app-env
environment: environment:
- APP_RELEASE=${APP_RELEASE:-v0.25.2}
- WEB_URL=${SERVICE_FQDN_PLANE} - WEB_URL=${SERVICE_FQDN_PLANE}
- DEBUG=${DEBUG:-0} - DEBUG=${DEBUG:-0}
- CORS_ALLOWED_ORIGINS=${CORS_ALLOWED_ORIGIN:-http://localhost} - CORS_ALLOWED_ORIGINS=${CORS_ALLOWED_ORIGIN:-http://localhost}
@@ -54,7 +55,7 @@ services:
- SERVICE_FQDN_PLANE - SERVICE_FQDN_PLANE
- FILE_SIZE_LIMIT=${FILE_SIZE_LIMIT:-5242880} - FILE_SIZE_LIMIT=${FILE_SIZE_LIMIT:-5242880}
- BUCKET_NAME=${BUCKET_NAME:-uploads} - BUCKET_NAME=${BUCKET_NAME:-uploads}
image: makeplane/plane-proxy:stable image: makeplane/plane-proxy:${APP_RELEASE:-v0.25.1}
depends_on: depends_on:
- web - web
- api - api
@@ -66,8 +67,7 @@ services:
retries: 15 retries: 15
web: web:
<<: *app-env image: makeplane/plane-frontend:${APP_RELEASE:-v0.25.1}
image: makeplane/plane-frontend:stable
command: node web/server.js web command: node web/server.js web
depends_on: depends_on:
- api - api
@@ -78,8 +78,7 @@ services:
timeout: 10s timeout: 10s
retries: 15 retries: 15
space: space:
<<: *app-env image: makeplane/plane-space:${APP_RELEASE:-v0.25.1}
image: makeplane/plane-space:stable
command: node space/server.js space command: node space/server.js space
depends_on: depends_on:
- api - api
@@ -92,8 +91,7 @@ services:
retries: 15 retries: 15
admin: admin:
<<: *app-env image: makeplane/plane-admin:${APP_RELEASE:-v0.25.1}
image: makeplane/plane-admin:stable
command: node admin/server.js admin command: node admin/server.js admin
depends_on: depends_on:
- api - api
@@ -106,7 +104,7 @@ services:
live: live:
<<: *app-env <<: *app-env
image: makeplane/plane-live:stable image: makeplane/plane-live:${APP_RELEASE:-v0.25.1}
command: node live/dist/server.js live command: node live/dist/server.js live
depends_on: depends_on:
- api - api
@@ -119,7 +117,7 @@ services:
api: api:
<<: *app-env <<: *app-env
image: makeplane/plane-backend:stable image: makeplane/plane-backend:${APP_RELEASE:-v0.25.1}
command: ./bin/docker-entrypoint-api.sh command: ./bin/docker-entrypoint-api.sh
volumes: volumes:
- logs_api:/code/plane/logs - logs_api:/code/plane/logs
@@ -134,7 +132,7 @@ services:
worker: worker:
<<: *app-env <<: *app-env
image: makeplane/plane-backend:stable image: makeplane/plane-backend:${APP_RELEASE:-v0.25.1}
command: ./bin/docker-entrypoint-worker.sh command: ./bin/docker-entrypoint-worker.sh
volumes: volumes:
- logs_worker:/code/plane/logs - logs_worker:/code/plane/logs
@@ -150,7 +148,7 @@ services:
beat-worker: beat-worker:
<<: *app-env <<: *app-env
image: makeplane/plane-backend:stable image: makeplane/plane-backend:${APP_RELEASE:-v0.25.1}
command: ./bin/docker-entrypoint-beat.sh command: ./bin/docker-entrypoint-beat.sh
volumes: volumes:
- logs_beat-worker:/code/plane/logs - logs_beat-worker:/code/plane/logs
@@ -166,7 +164,7 @@ services:
migrator: migrator:
<<: *app-env <<: *app-env
image: makeplane/plane-backend:stable image: makeplane/plane-backend:${APP_RELEASE:-v0.25.1}
restart: "no" restart: "no"
command: ./bin/docker-entrypoint-migrator.sh command: ./bin/docker-entrypoint-migrator.sh
volumes: volumes:

View File

@@ -318,7 +318,7 @@ services:
# NEXT_ANALYTICS_BACKEND_PROVIDER=bigquery # NEXT_ANALYTICS_BACKEND_PROVIDER=bigquery
- 'OPENAI_API_KEY=${OPENAI_API_KEY}' - 'OPENAI_API_KEY=${OPENAI_API_KEY}'
supabase-db: supabase-db:
image: supabase/postgres:15.6.1.146 image: supabase/postgres:15.8.1.048
healthcheck: healthcheck:
test: pg_isready -U postgres -h 127.0.0.1 test: pg_isready -U postgres -h 127.0.0.1
interval: 5s interval: 5s

View File

@@ -0,0 +1,60 @@
# documentation: https://wakapi.dev/
# slogan: A minimalist, self-hosted WakaTime-compatible backend for coding statistics
# tags: productivity, self-hosted, developer-tools, time-tracker, wakatime, wakatime-api, coding-statistics, statistics, timetracking, analytics
# logo: svgs/wakapi.svg
# port: 3000
services:
wakapi:
image: ghcr.io/muety/wakapi:latest
environment:
- SERVICE_FQDN_WAKAPI_3000
- TZ=${TIMEZONE:-Europe/Berlin}
- WAKAPI_SERVER_LISTEN_IPV6="-"
- WAKAPI_ENV=${WAKAPI_ENVIRONMENT:-production}
- WAKAPI_SECURITY_PASSWORD_SALT=${SERVICE_BASE64_64_PASSWORDSALT}
- WAKAPI_SECURITY_EXPOSE_METRICS=${WAKAPI_SECURITY_EXPOSE_METRICS:-false}
# Database configuration
- WAKAPI_DB_TYPE=postgres
- WAKAPI_DB_NAME=${WAKAPI_DB_NAME:-wakapi}
- WAKAPI_DB_USER=${SERVICE_USER_DATABASE}
- WAKAPI_DB_PASSWORD=${SERVICE_PASSWORD_DATABASE}
- WAKAPI_DB_HOST=${WAKAPI_DB_HOST:-postgres}
- WAKAPI_DB_PORT=${WAKAPI_DB_PORT:-5432}
# SMTP configuration
- WAKAPI_MAIL_ENABLED=${WAKAPI_MAIL_ENABLED:-false}
- WAKAPI_MAIL_PROVIDER=smtp #only smtp supported
- WAKAPI_MAIL_SENDER=${WAKAPI_MAIL_SENDER}
- WAKAPI_MAIL_SMTP_HOST=${WAKAPI_MAIL_SMTP_HOST}
- WAKAPI_MAIL_SMTP_PORT=${WAKAPI_MAIL_SMTP_PORT:-587}
- WAKAPI_MAIL_SMTP_USERNAME=${WAKAPI_MAIL_SMTP_USERNAME}
- WAKAPI_MAIL_SMTP_PASSWORD=${WAKAPI_MAIL_SMTP_PASSWORD}
volumes:
- wakapi-data:/data
depends_on:
postgres:
condition: service_healthy
healthcheck:
test: ["CMD-SHELL", "wget -qO- http://127.0.0.1:3000/"]
interval: 2s
timeout: 10s
retries: 15
postgres:
image: postgres:16-alpine
volumes:
- wakapi-postgres-data:/var/lib/postgresql/data
environment:
- POSTGRES_USER=${SERVICE_USER_DATABASE}
- POSTGRES_PASSWORD=${SERVICE_PASSWORD_DATABASE}
- POSTGRES_DB=${WAKAPI_DB_NAME:-wakapi}
- POSTGRES_PORT=${WAKAPI_DB_PORT:-5432}
healthcheck:
test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"]
interval: 5s
timeout: 20s
retries: 10

View File

@@ -11,7 +11,7 @@ services:
- SERVICE_FQDN_ZIPLINE_3000 - SERVICE_FQDN_ZIPLINE_3000
- CORE_RETURN_HTTPS=${CORE_RETURN_HTTPS:-false} - CORE_RETURN_HTTPS=${CORE_RETURN_HTTPS:-false}
- CORE_SECRET=${SERVICE_PASSWORD_64_ZIPLINE} - CORE_SECRET=${SERVICE_PASSWORD_64_ZIPLINE}
- CORE_DATABASE_URL=postgres://${SERVICE_USER_POSTGRES}:${SERVICE_PASSWORD_POSTGRES}@postgres/${POSTGRES_DB:-zipline-db} - DATABASE_URL=postgres://${SERVICE_USER_POSTGRES}:${SERVICE_PASSWORD_POSTGRES}@postgres/${POSTGRES_DB:-zipline-db}
- CORE_LOGGER=${CORE_LOGGER:-true} - CORE_LOGGER=${CORE_LOGGER:-true}
# Default credentials are "administrator" and "password" # Default credentials are "administrator" and "password"
volumes: volumes:

File diff suppressed because one or more lines are too long

View File

@@ -16,7 +16,7 @@ class LoginTest extends DuskTestCase
* *
* @throws Throwable * @throws Throwable
*/ */
public function testLogin() public function test_login()
{ {
$this->browse(callback: function (Browser $browser) { $this->browse(callback: function (Browser $browser) {
$browser->loginWithRootUser() $browser->loginWithRootUser()

View File

@@ -16,7 +16,7 @@ class ProjectAddNewTest extends DuskTestCase
* *
* @throws Throwable * @throws Throwable
*/ */
public function testLogin() public function test_login()
{ {
$this->browse(function (Browser $browser) { $this->browse(function (Browser $browser) {
$browser->loginWithRootUser() $browser->loginWithRootUser()

Some files were not shown because too many files have changed in this diff Show More