@stacksjs/ts-cloud 0.7.56 → 0.7.57
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/alerts/alerts.test.d.ts +1 -0
- package/dist/alerts/delivery.d.ts +45 -0
- package/dist/alerts/evaluator.d.ts +12 -0
- package/dist/alerts/health.d.ts +34 -0
- package/dist/alerts/index.d.ts +6 -0
- package/dist/alerts/model.d.ts +170 -0
- package/dist/alerts/store.d.ts +90 -0
- package/dist/alerts/telemetry.d.ts +3 -0
- package/dist/api/client.d.ts +197 -0
- package/dist/api/handler.d.ts +18 -0
- package/dist/api/handler.test.d.ts +1 -0
- package/dist/api/index.d.ts +6 -0
- package/dist/api/openapi.d.ts +2 -0
- package/dist/api/service.d.ts +28 -0
- package/dist/api/types.d.ts +119 -0
- package/dist/auth/encryption.d.ts +3 -0
- package/dist/auth/index.d.ts +8 -0
- package/dist/auth/mailer.d.ts +9 -0
- package/dist/auth/oidc.d.ts +36 -0
- package/dist/auth/oidc.test.d.ts +1 -0
- package/dist/auth/store.d.ts +121 -0
- package/dist/auth/store.test.d.ts +1 -0
- package/dist/auth/totp.d.ts +11 -0
- package/dist/auth/totp.test.d.ts +1 -0
- package/dist/auth/types.d.ts +138 -0
- package/dist/automation/index.d.ts +2 -0
- package/dist/automation/store.d.ts +46 -0
- package/dist/automation/store.test.d.ts +1 -0
- package/dist/automation/types.d.ts +66 -0
- package/dist/aws/acm.d.ts +0 -4
- package/dist/aws/application-autoscaling.d.ts +0 -5
- package/dist/aws/backup.d.ts +42 -0
- package/dist/aws/bedrock.d.ts +0 -5
- package/dist/aws/client.d.ts +3 -6
- package/dist/aws/cloudformation.d.ts +0 -4
- package/dist/aws/cloudfront-media.test.d.ts +1 -0
- package/dist/aws/cloudfront-origin.test.d.ts +1 -0
- package/dist/aws/cloudfront.d.ts +87 -3
- package/dist/aws/cloudwatch-logs.d.ts +2 -4
- package/dist/aws/cloudwatch.d.ts +1 -1
- package/dist/aws/comprehend.d.ts +0 -5
- package/dist/aws/connect.d.ts +0 -4
- package/dist/aws/cost-explorer-cache.d.ts +1 -15
- package/dist/aws/cost-explorer.d.ts +18 -9
- package/dist/aws/cost-explorer.test.d.ts +1 -0
- package/dist/aws/dynamodb.d.ts +0 -4
- package/dist/aws/ec2.d.ts +0 -4
- package/dist/aws/ecr.d.ts +0 -4
- package/dist/aws/ecs.d.ts +17 -7
- package/dist/aws/efs.d.ts +0 -4
- package/dist/aws/elasticache.d.ts +0 -4
- package/dist/aws/elbv2.d.ts +0 -7
- package/dist/aws/email.d.ts +0 -10
- package/dist/aws/eventbridge.d.ts +0 -4
- package/dist/aws/iam.d.ts +1 -5
- package/dist/aws/imap-server.d.ts +0 -7
- package/dist/aws/index.d.ts +4 -3
- package/dist/aws/index.js +31 -31
- package/dist/aws/kendra.d.ts +0 -5
- package/dist/aws/lambda.d.ts +3 -5
- package/dist/aws/opensearch.d.ts +0 -4
- package/dist/aws/personalize.d.ts +0 -5
- package/dist/aws/polly.d.ts +0 -5
- package/dist/aws/rds.d.ts +59 -4
- package/dist/aws/rekognition.d.ts +0 -5
- package/dist/aws/route53-domains.d.ts +0 -4
- package/dist/aws/route53.d.ts +0 -4
- package/dist/aws/s3.d.ts +10 -6
- package/dist/aws/scheduler.d.ts +0 -4
- package/dist/aws/secrets-manager.d.ts +0 -4
- package/dist/aws/setup-sms.d.ts +0 -14
- package/dist/aws/sms.d.ts +0 -10
- package/dist/aws/smtp-server.d.ts +0 -11
- package/dist/aws/sns.d.ts +0 -4
- package/dist/aws/sqs.d.ts +0 -4
- package/dist/aws/ssm.d.ts +0 -4
- package/dist/aws/sts.d.ts +0 -4
- package/dist/aws/support.d.ts +0 -4
- package/dist/aws/textract.d.ts +0 -5
- package/dist/aws/transcribe.d.ts +0 -4
- package/dist/aws/translate.d.ts +0 -5
- package/dist/aws/voice.d.ts +0 -11
- package/dist/aws/xray.d.ts +1 -0
- package/dist/backups/aws-database-source.d.ts +19 -0
- package/dist/backups/aws-database-source.test.d.ts +1 -0
- package/dist/backups/aws-infrastructure-source.d.ts +43 -0
- package/dist/backups/aws-infrastructure-source.test.d.ts +1 -0
- package/dist/backups/control-plane-source.d.ts +16 -0
- package/dist/backups/control-plane-source.test.d.ts +1 -0
- package/dist/backups/docker-volume-source.d.ts +31 -0
- package/dist/backups/docker-volume-source.test.d.ts +1 -0
- package/dist/backups/filesystem-source.d.ts +34 -0
- package/dist/backups/filesystem-source.test.d.ts +1 -0
- package/dist/backups/index.d.ts +10 -0
- package/dist/backups/logical-database-source.d.ts +16 -0
- package/dist/backups/logical-database-source.test.d.ts +1 -0
- package/dist/backups/model.d.ts +121 -0
- package/dist/backups/s3-destination.d.ts +85 -0
- package/dist/backups/s3-destination.test.d.ts +1 -0
- package/dist/backups/service.d.ts +80 -0
- package/dist/backups/service.test.d.ts +1 -0
- package/dist/backups/store.d.ts +30 -0
- package/dist/backups/store.test.d.ts +1 -0
- package/dist/bin/cli.js +3360 -1802
- package/dist/{chunk-tjjgajbh.js → chunk-01d86gt1.js} +301 -9
- package/dist/{chunk-73vcqg6z.js → chunk-0z43x8re.js} +7 -7
- package/dist/{chunk-tnztxpcb.js → chunk-32e7ya18.js} +61 -49
- package/dist/{chunk-qpj3edwz.js → chunk-4cjrg98a.js} +3 -7
- package/dist/{chunk-hsk6fe6x.js → chunk-50jpda9q.js} +2 -2
- package/dist/{chunk-93hjhs78.js → chunk-703nkybg.js} +1 -1
- package/dist/{chunk-d5vqwj8s.js → chunk-9m6b4m74.js} +755 -720
- package/dist/chunk-e05phx5f.js +10 -0
- package/dist/{chunk-f29w04w5.js → chunk-exbcsab2.js} +10 -4
- package/dist/{chunk-eq08r166.js → chunk-f55nkpvb.js} +2 -2
- package/dist/{chunk-3bfv1z4v.js → chunk-fv1bj3yt.js} +63 -56
- package/dist/chunk-fw3q88wk.js +48641 -0
- package/dist/{chunk-3knnr7wh.js → chunk-he9a874b.js} +170 -2
- package/dist/{chunk-zn0nxxa8.js → chunk-hpv68b4a.js} +1070 -1070
- package/dist/chunk-k114qwg9.js +12 -0
- package/dist/{chunk-r16e02bc.js → chunk-vdk53yyq.js} +3900 -4101
- package/dist/{chunk-jp2a8yad.js → chunk-vvkd46k1.js} +15 -13
- package/dist/{chunk-vd87cpvn.js → chunk-wj3s95p9.js} +62 -46
- package/dist/{chunk-mj1tmhte.js → chunk-x9s0cqfx.js} +1 -1
- package/dist/{chunk-3rsfns7x.js → chunk-ybcz6sxc.js} +2048 -387
- package/dist/{chunk-arsh1g5h.js → chunk-zqtpg06c.js} +14 -11
- package/dist/compose/index.d.ts +6 -0
- package/dist/compose/parser.d.ts +13 -0
- package/dist/compose/parser.test.d.ts +1 -0
- package/dist/compose/runtime.d.ts +10 -0
- package/dist/compose/service.d.ts +18 -0
- package/dist/compose/store.d.ts +59 -0
- package/dist/compose/store.test.d.ts +1 -0
- package/dist/compose/templates.d.ts +17 -0
- package/dist/compose/types.d.ts +164 -0
- package/dist/configuration/backends.d.ts +66 -0
- package/dist/configuration/backends.test.d.ts +1 -0
- package/dist/configuration/dotenv.d.ts +14 -0
- package/dist/configuration/dotenv.test.d.ts +1 -0
- package/dist/configuration/index.d.ts +6 -0
- package/dist/configuration/migrate.d.ts +10 -0
- package/dist/configuration/migrate.test.d.ts +1 -0
- package/dist/configuration/model.d.ts +50 -0
- package/dist/configuration/service.d.ts +144 -0
- package/dist/configuration/service.test.d.ts +1 -0
- package/dist/configuration/store.d.ts +33 -0
- package/dist/configuration/store.test.d.ts +1 -0
- package/dist/control-plane/authorization.d.ts +24 -0
- package/dist/control-plane/authorization.test.d.ts +1 -0
- package/dist/control-plane/index.d.ts +8 -0
- package/dist/control-plane/migrations.d.ts +7 -0
- package/dist/control-plane/search.d.ts +25 -0
- package/dist/control-plane/store.d.ts +117 -0
- package/dist/control-plane/store.test.d.ts +1 -0
- package/dist/control-plane/types.d.ts +381 -0
- package/dist/cost/reporting.d.ts +24 -0
- package/dist/cost/reporting.test.d.ts +1 -0
- package/dist/cost/resource-inventory.d.ts +32 -0
- package/dist/cost/resource-inventory.test.d.ts +1 -0
- package/dist/cost/resource-optimization.d.ts +59 -0
- package/dist/cost/resource-optimization.test.d.ts +1 -0
- package/dist/data-services/adapters.d.ts +39 -0
- package/dist/data-services/aws-transports.d.ts +29 -0
- package/dist/data-services/aws-transports.test.d.ts +1 -0
- package/dist/data-services/capabilities.d.ts +2 -0
- package/dist/data-services/data-services.test.d.ts +1 -0
- package/dist/data-services/docker-transport.d.ts +55 -0
- package/dist/data-services/docker-transport.test.d.ts +1 -0
- package/dist/data-services/index.d.ts +8 -0
- package/dist/data-services/model.d.ts +79 -0
- package/dist/data-services/secrets.d.ts +13 -0
- package/dist/data-services/secrets.test.d.ts +1 -0
- package/dist/data-services/service.d.ts +51 -0
- package/dist/data-services/store.d.ts +17 -0
- package/dist/deploy/container-image.d.ts +28 -0
- package/dist/deploy/container-image.test.d.ts +1 -0
- package/dist/deploy/dashboard-audit.test.d.ts +1 -0
- package/dist/deploy/dashboard-auth.d.ts +4 -23
- package/dist/deploy/dashboard-backups.integration.test.d.ts +1 -0
- package/dist/deploy/dashboard-configuration.integration.test.d.ts +1 -0
- package/dist/deploy/dashboard-control-plane.d.ts +37 -0
- package/dist/deploy/dashboard-control-plane.test.d.ts +1 -0
- package/dist/deploy/dashboard-data-services.integration.test.d.ts +1 -0
- package/dist/deploy/dashboard-environment-scope.test.d.ts +1 -0
- package/dist/deploy/dashboard-guard.d.ts +12 -0
- package/dist/deploy/dashboard-guard.test.d.ts +1 -0
- package/dist/deploy/dashboard-identities.d.ts +15 -0
- package/dist/deploy/dashboard-identities.test.d.ts +1 -0
- package/dist/deploy/dashboard-jobs.integration.test.d.ts +1 -0
- package/dist/deploy/dashboard-login-page.d.ts +5 -5
- package/dist/deploy/dashboard-login-page.test.d.ts +1 -0
- package/dist/deploy/dashboard-oidc.integration.test.d.ts +1 -0
- package/dist/deploy/dashboard-onboarding.integration.test.d.ts +1 -0
- package/dist/deploy/dashboard-policy.d.ts +4 -2
- package/dist/deploy/dashboard-queue-worker.integration.test.d.ts +1 -0
- package/dist/deploy/dashboard-release.integration.test.d.ts +1 -0
- package/dist/deploy/dashboard-route-manifest.d.ts +14 -0
- package/dist/deploy/dashboard-route-manifest.test.d.ts +1 -0
- package/dist/deploy/dashboard-security.integration.test.d.ts +1 -0
- package/dist/deploy/dashboard-session.d.ts +3 -14
- package/dist/deploy/dashboard-source.integration.test.d.ts +1 -0
- package/dist/deploy/dashboard-users.d.ts +3 -0
- package/dist/deploy/fullstack-container.d.ts +87 -0
- package/dist/deploy/fullstack-container.test.d.ts +1 -0
- package/dist/deploy/index.d.ts +7 -2
- package/dist/deploy/index.js +65 -25
- package/dist/deploy/local-dashboard-server.d.ts +30 -0
- package/dist/deploy/quick-deploy.d.ts +1 -1
- package/dist/deploy/serverless-operations.d.ts +1 -0
- package/dist/deploy/site-target.d.ts +16 -0
- package/dist/deploy/static-api-origin.d.ts +107 -0
- package/dist/deploy/static-api-origin.test.d.ts +1 -0
- package/dist/deploy/static-site-helper.d.ts +0 -16
- package/dist/deploy/telemetry-access.d.ts +5 -0
- package/dist/deploy/telemetry-access.test.d.ts +1 -0
- package/dist/deploy/telemetry-collection.d.ts +44 -0
- package/dist/deploy/telemetry-collection.test.d.ts +1 -0
- package/dist/dns/index.js +3 -3
- package/dist/dns/route53-adapter.d.ts +1 -1
- package/dist/drivers/hetzner/cloud-init.d.ts +1 -1
- package/dist/drivers/index.d.ts +2 -2
- package/dist/drivers/index.js +6 -6
- package/dist/drivers/shared/notifications.d.ts +1 -1
- package/dist/drivers/shared/rpx-gateway.d.ts +1 -0
- package/dist/fleet/fleet.test.d.ts +1 -0
- package/dist/fleet/index.d.ts +144 -0
- package/dist/fleet/queue.d.ts +3 -0
- package/dist/fleet/ssh-driver.d.ts +34 -0
- package/dist/index.d.ts +28 -4
- package/dist/index.js +1132 -424
- package/dist/jobs/adapters.d.ts +23 -0
- package/dist/jobs/index.d.ts +7 -0
- package/dist/jobs/jobs.test.d.ts +1 -0
- package/dist/jobs/model.d.ts +100 -0
- package/dist/jobs/provider-adapters.d.ts +49 -0
- package/dist/jobs/reconcile.d.ts +19 -0
- package/dist/jobs/schedule.d.ts +9 -0
- package/dist/jobs/service.d.ts +30 -0
- package/dist/jobs/store.d.ts +48 -0
- package/dist/maintenance/drivers.d.ts +117 -0
- package/dist/maintenance/index.d.ts +6 -0
- package/dist/maintenance/maintenance.test.d.ts +1 -0
- package/dist/maintenance/manifest.d.ts +15 -0
- package/dist/maintenance/queue.d.ts +9 -0
- package/dist/maintenance/service.d.ts +31 -0
- package/dist/maintenance/store.d.ts +84 -0
- package/dist/maintenance/types.d.ts +192 -0
- package/dist/media.d.ts +62 -0
- package/dist/media.test.d.ts +1 -0
- package/dist/object-storage/index.d.ts +0 -24
- package/dist/onboarding/archive.d.ts +12 -0
- package/dist/onboarding/artifact-store.d.ts +22 -0
- package/dist/onboarding/detection.d.ts +8 -0
- package/dist/onboarding/index.d.ts +9 -0
- package/dist/onboarding/migrations.d.ts +3 -0
- package/dist/onboarding/onboarding.test.d.ts +1 -0
- package/dist/onboarding/plan.d.ts +3 -0
- package/dist/onboarding/registry.d.ts +41 -0
- package/dist/onboarding/service.d.ts +16 -0
- package/dist/onboarding/store.d.ts +30 -0
- package/dist/onboarding/types.d.ts +204 -0
- package/dist/placement/builds.d.ts +20 -0
- package/dist/placement/drivers.d.ts +54 -0
- package/dist/placement/index.d.ts +6 -0
- package/dist/placement/placement.test.d.ts +1 -0
- package/dist/placement/queue.d.ts +4 -0
- package/dist/placement/service.d.ts +34 -0
- package/dist/placement/store.d.ts +49 -0
- package/dist/placement/types.d.ts +109 -0
- package/dist/preview/index.d.ts +3 -0
- package/dist/preview/service.d.ts +45 -0
- package/dist/preview/service.test.d.ts +1 -0
- package/dist/preview/store.d.ts +47 -0
- package/dist/preview/store.test.d.ts +1 -0
- package/dist/preview/types.d.ts +99 -0
- package/dist/push/apns.d.ts +0 -26
- package/dist/push/fcm.d.ts +0 -23
- package/dist/push/index.d.ts +2 -2
- package/dist/push/index.js +1 -1
- package/dist/queue/deployment-handlers.d.ts +27 -0
- package/dist/queue/deployment-handlers.test.d.ts +1 -0
- package/dist/queue/index.d.ts +4 -0
- package/dist/queue/queue.d.ts +57 -0
- package/dist/queue/queue.test.d.ts +1 -0
- package/dist/queue/types.d.ts +93 -0
- package/dist/queue/worker.d.ts +32 -0
- package/dist/queue/worker.test.d.ts +1 -0
- package/dist/regions/drivers.d.ts +139 -0
- package/dist/regions/index.d.ts +5 -0
- package/dist/regions/queue.d.ts +4 -0
- package/dist/regions/regions.test.d.ts +1 -0
- package/dist/regions/service.d.ts +23 -0
- package/dist/regions/store.d.ts +41 -0
- package/dist/regions/types.d.ts +132 -0
- package/dist/release/index.d.ts +6 -0
- package/dist/release/queue.d.ts +15 -0
- package/dist/release/queue.test.d.ts +1 -0
- package/dist/release/runtime.d.ts +35 -0
- package/dist/release/runtime.test.d.ts +1 -0
- package/dist/release/service.d.ts +28 -0
- package/dist/release/store.d.ts +88 -0
- package/dist/release/store.test.d.ts +1 -0
- package/dist/release/strategy.d.ts +8 -0
- package/dist/release/types.d.ts +103 -0
- package/dist/runtime/adapters/aws.d.ts +5 -0
- package/dist/runtime/adapters/docker.d.ts +53 -0
- package/dist/runtime/adapters/systemd.d.ts +26 -0
- package/dist/runtime/index.d.ts +9 -0
- package/dist/runtime/inventory.d.ts +6 -0
- package/dist/runtime/model.d.ts +130 -0
- package/dist/runtime/normalize.d.ts +5 -0
- package/dist/runtime/operations.d.ts +113 -0
- package/dist/runtime/service.d.ts +32 -0
- package/dist/runtime/streams.d.ts +49 -0
- package/dist/security/artifacts.d.ts +105 -0
- package/dist/security/artifacts.test.d.ts +1 -0
- package/dist/security/container-release.d.ts +35 -0
- package/dist/security/container-release.test.d.ts +1 -0
- package/dist/security/index.d.ts +8 -0
- package/dist/security/integration.d.ts +41 -0
- package/dist/security/integration.test.d.ts +1 -0
- package/dist/security/posture-store.d.ts +80 -0
- package/dist/security/posture-store.test.d.ts +1 -0
- package/dist/security/pre-deploy-scanner.d.ts +0 -4
- package/dist/security/scanners.d.ts +81 -0
- package/dist/security/scanners.test.d.ts +1 -0
- package/dist/security/types.d.ts +150 -0
- package/dist/source/git-workspace.d.ts +26 -0
- package/dist/source/git-workspace.test.d.ts +1 -0
- package/dist/source/index.d.ts +6 -0
- package/dist/source/providers.d.ts +199 -0
- package/dist/source/providers.test.d.ts +1 -0
- package/dist/source/service.d.ts +18 -0
- package/dist/source/store.d.ts +149 -0
- package/dist/source/store.test.d.ts +1 -0
- package/dist/source/types.d.ts +191 -0
- package/dist/source/webhooks.d.ts +33 -0
- package/dist/source/webhooks.test.d.ts +1 -0
- package/dist/ssl/acme-client.d.ts +0 -6
- package/dist/storage/compose.d.ts +4 -0
- package/dist/storage/compose.test.d.ts +1 -0
- package/dist/storage/drivers.d.ts +107 -0
- package/dist/storage/drivers.test.d.ts +1 -0
- package/dist/storage/index.d.ts +5 -0
- package/dist/storage/model.d.ts +112 -0
- package/dist/storage/service.d.ts +95 -0
- package/dist/storage/storage.test.d.ts +1 -0
- package/dist/storage/store.d.ts +40 -0
- package/dist/telemetry/correlation.test.d.ts +1 -0
- package/dist/telemetry/index.d.ts +4 -0
- package/dist/telemetry/model.d.ts +145 -0
- package/dist/telemetry/policy.d.ts +8 -0
- package/dist/telemetry/policy.test.d.ts +1 -0
- package/dist/telemetry/redaction.d.ts +9 -0
- package/dist/telemetry/store.d.ts +34 -0
- package/dist/telemetry/store.test.d.ts +1 -0
- package/dist/ui/404.html +1506 -17
- package/dist/ui/accept-invitation.html +1163 -0
- package/dist/ui/{server/backups.html → access-denied.html} +344 -55
- package/dist/ui/account/automation.html +1669 -0
- package/dist/ui/account/security.html +1646 -0
- package/dist/ui/applications/compose.html +1590 -0
- package/dist/ui/applications/new.html +1868 -0
- package/dist/ui/data/backups.html +1757 -0
- package/dist/ui/data/services.html +1723 -0
- package/dist/ui/data/volumes.html +1639 -0
- package/dist/ui/index.html +392 -29
- package/dist/ui/integrations.html +1865 -0
- package/dist/ui/operations/alerts.html +1610 -0
- package/dist/ui/operations/configuration.html +1746 -0
- package/dist/ui/operations/jobs.html +1709 -0
- package/dist/ui/operations/maintenance.html +1540 -0
- package/dist/ui/operations/observability.html +1742 -0
- package/dist/ui/{serverless/scheduler.html → operations/previews.html} +447 -46
- package/dist/ui/operations/queue.html +1615 -0
- package/dist/ui/{server/workers.html → operations/regions.html} +413 -49
- package/dist/ui/operations/releases.html +1596 -0
- package/dist/ui/operations/workloads.html +1775 -0
- package/dist/ui/security.html +1767 -0
- package/dist/ui/server/actions.html +446 -57
- package/dist/ui/server/activity.html +346 -1
- package/dist/ui/server/capacity.html +1542 -0
- package/dist/ui/server/database.html +443 -36
- package/dist/ui/server/deployments.html +439 -53
- package/dist/ui/server/diagnostics.html +346 -1
- package/dist/ui/server/firewall.html +476 -50
- package/dist/ui/server/fleet.html +1577 -0
- package/dist/ui/server/logs.html +389 -25
- package/dist/ui/server/metrics.html +346 -1
- package/dist/ui/server/security.html +346 -1
- package/dist/ui/server/services.html +421 -46
- package/dist/ui/server/sites.html +476 -95
- package/dist/ui/server/ssh-keys.html +476 -46
- package/dist/ui/server/team.html +700 -77
- package/dist/ui/server/terminal.html +444 -54
- package/dist/ui/serverless/alarms.html +430 -42
- package/dist/ui/serverless/assets.html +421 -46
- package/dist/ui/serverless/cost.html +346 -1
- package/dist/ui/serverless/data.html +422 -47
- package/dist/ui/serverless/deployments.html +421 -46
- package/dist/ui/serverless/firewall.html +346 -1
- package/dist/ui/serverless/functions.html +423 -48
- package/dist/ui/serverless/logs.html +389 -25
- package/dist/ui/serverless/metrics.html +346 -1
- package/dist/ui/serverless/queues.html +448 -62
- package/dist/ui/serverless/secrets.html +448 -42
- package/dist/ui/serverless/traces.html +350 -5
- package/dist/ui/serverless.html +434 -58
- package/dist/ui-src/pages/404.stx +18 -0
- package/dist/ui-src/pages/accept-invitation.stx +50 -0
- package/dist/ui-src/pages/access-denied.stx +18 -0
- package/dist/ui-src/pages/account/automation.stx +187 -0
- package/dist/ui-src/pages/account/security.stx +249 -0
- package/dist/ui-src/pages/applications/compose.stx +38 -0
- package/dist/ui-src/pages/applications/new.stx +76 -0
- package/dist/ui-src/pages/data/backups.stx +214 -0
- package/dist/ui-src/pages/data/services.stx +257 -0
- package/dist/ui-src/pages/data/volumes.stx +40 -0
- package/dist/ui-src/pages/index.stx +24 -10
- package/dist/ui-src/pages/integrations.stx +186 -0
- package/dist/ui-src/pages/operations/alerts.stx +40 -0
- package/dist/ui-src/pages/operations/configuration.stx +164 -0
- package/dist/ui-src/pages/operations/jobs.stx +238 -0
- package/dist/ui-src/pages/operations/maintenance.stx +15 -0
- package/dist/ui-src/pages/operations/observability.stx +76 -0
- package/dist/ui-src/pages/operations/previews.stx +62 -0
- package/dist/ui-src/pages/operations/queue.stx +158 -0
- package/dist/ui-src/pages/operations/regions.stx +12 -0
- package/dist/ui-src/pages/operations/releases.stx +39 -0
- package/dist/ui-src/pages/operations/workloads.stx +151 -0
- package/dist/ui-src/pages/partials/head.stx +148 -15
- package/dist/ui-src/pages/partials/nav.stx +491 -74
- package/dist/ui-src/pages/partials/op-confirm.stx +6 -6
- package/dist/ui-src/pages/security.stx +264 -0
- package/dist/ui-src/pages/server/actions.stx +17 -26
- package/dist/ui-src/pages/server/capacity.stx +16 -0
- package/dist/ui-src/pages/server/database.stx +31 -16
- package/dist/ui-src/pages/server/deployments.stx +28 -30
- package/dist/ui-src/pages/server/firewall.stx +25 -30
- package/dist/ui-src/pages/server/fleet.stx +10 -0
- package/dist/ui-src/pages/server/logs.stx +11 -9
- package/dist/ui-src/pages/server/metrics.stx +8 -16
- package/dist/ui-src/pages/server/services.stx +19 -28
- package/dist/ui-src/pages/server/sites.stx +75 -72
- package/dist/ui-src/pages/server/ssh-keys.stx +24 -30
- package/dist/ui-src/pages/server/team.stx +286 -149
- package/dist/ui-src/pages/server/terminal.stx +6 -28
- package/dist/ui-src/pages/serverless/alarms.stx +17 -31
- package/dist/ui-src/pages/serverless/assets.stx +13 -22
- package/dist/ui-src/pages/serverless/cost.stx +15 -3
- package/dist/ui-src/pages/serverless/data.stx +12 -25
- package/dist/ui-src/pages/serverless/deployments.stx +14 -23
- package/dist/ui-src/pages/serverless/firewall.stx +5 -1
- package/dist/ui-src/pages/serverless/functions.stx +20 -26
- package/dist/ui-src/pages/serverless/logs.stx +11 -10
- package/dist/ui-src/pages/serverless/metrics.stx +18 -17
- package/dist/ui-src/pages/serverless/queues.stx +34 -42
- package/dist/ui-src/pages/serverless/secrets.stx +31 -34
- package/dist/ui-src/pages/serverless/traces.stx +2 -6
- package/dist/ui-src/pages/serverless.stx +40 -74
- package/package.json +11 -11
- package/dist/chunk-b17vf1g1.js +0 -13787
- package/dist/chunk-b82pbxyp.js +0 -1572
- package/dist/chunk-pqfzdg68.js +0 -12
- package/dist/chunk-z58fqnjm.js +0 -10
- package/dist/ui-src/pages/server/backups.stx +0 -91
- package/dist/ui-src/pages/server/workers.stx +0 -99
- package/dist/ui-src/pages/serverless/scheduler.stx +0 -89
|
@@ -7,18 +7,31 @@ const server = __d?.server ?? { name: 'acme-production-app' }
|
|
|
7
7
|
// Members reach this page for their own sites; box-level CLI hints and the
|
|
8
8
|
// server crumb are not theirs to act on.
|
|
9
9
|
const isMember = (__d?.viewer?.role ?? 'admin') === 'member'
|
|
10
|
+
const viewerCapabilities = __d?.viewer?.capabilities ?? []
|
|
11
|
+
const canRollback = !isMember && viewerCapabilities.includes('deployments:rollback')
|
|
10
12
|
const initialDeps = __d?.serverDeploymentsDetail ?? []
|
|
11
13
|
const deploymentChart = renderDeploymentSparkline(initialDeps)
|
|
12
14
|
const deploymentsEmptyReason = __d?.deploymentsEmptyReason ?? 'No deployment history has been recorded yet.'
|
|
13
15
|
</script>
|
|
14
16
|
<script client>
|
|
17
|
+
import { useOpConfirm } from '../../functions/useOpConfirm.ts'
|
|
18
|
+
|
|
15
19
|
// Seeded from build-time data (stx server→client bridge), then live-refreshed.
|
|
16
20
|
const deps = state(initialDeps)
|
|
17
|
-
const
|
|
18
|
-
const
|
|
21
|
+
const initialFilters = new URLSearchParams(location.search)
|
|
22
|
+
const status = state(initialFilters.get('status') || 'all')
|
|
23
|
+
const site = state(initialFilters.get('site') || 'all')
|
|
19
24
|
const sites = derived(() => [...new Set(deps().map(d => d.site).filter(Boolean))])
|
|
20
25
|
const filtered = derived(() => deps().filter(d =>
|
|
21
26
|
(status() === 'all' || d.status === status()) && (site() === 'all' || d.site === site())))
|
|
27
|
+
function setFilter(name, value, signal) {
|
|
28
|
+
signal.set(value)
|
|
29
|
+
const url = new URL(location.href)
|
|
30
|
+
if (value === 'all') url.searchParams.delete(name)
|
|
31
|
+
else url.searchParams.set(name, value)
|
|
32
|
+
history.replaceState(null, '', url)
|
|
33
|
+
window.dispatchEvent(new Event('ts-cloud:filters-changed'))
|
|
34
|
+
}
|
|
22
35
|
function tone(s) { return s === 'success' ? 'ok' : (s === 'failed' ? 'bad' : 'warn') }
|
|
23
36
|
async function refresh() {
|
|
24
37
|
try { const r = await fetch('/api/dashboard-data'); if (!r.ok) return; const x = await r.json(); if (Array.isArray(x.serverDeploymentsDetail)) deps.set(x.serverDeploymentsDetail) } catch {}
|
|
@@ -26,27 +39,12 @@ async function refresh() {
|
|
|
26
39
|
onMount(() => { refresh() })
|
|
27
40
|
|
|
28
41
|
// Reactive operation runner (rollback) - typed-confirm bar + output.
|
|
29
|
-
const opOutput =
|
|
30
|
-
const
|
|
31
|
-
const
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
const canRun = derived(() => { const p = pending(); return !!p && typed() === p.confirm })
|
|
36
|
-
function askOp(operation, confirm, verb, to) { pending.set({ operation, confirm, verb, to: to || null }); typed.set('') }
|
|
37
|
-
function cancelOp() { pending.set(null) }
|
|
38
|
-
async function runOp() {
|
|
39
|
-
const p = pending()
|
|
40
|
-
if (!p || typed() !== p.confirm) return
|
|
41
|
-
pending.set(null); typed.set('')
|
|
42
|
-
opShown.set(true); opOutput.set('Running ' + p.operation + '...')
|
|
43
|
-
try {
|
|
44
|
-
const payload = p.to ? { operation: p.operation, confirm: p.confirm, to: p.to } : { operation: p.operation, confirm: p.confirm }
|
|
45
|
-
const res = await fetch('/api/server/operations/run', { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify(payload) })
|
|
46
|
-
const body = await res.json()
|
|
47
|
-
opOutput.set((body.ok ? 'OK ' : 'FAILED ') + (body.command || p.operation) + '\n\n' + (body.stdout || '') + (body.stderr ? '\n' + body.stderr : '') + (body.error ? '\n' + body.error : ''))
|
|
48
|
-
} catch (e) { opOutput.set('FAILED ' + p.operation + '\n\n' + ((e && e.message) || e)) }
|
|
49
|
-
}
|
|
42
|
+
const { opOutput, opShown, pending, typed, busy, confirmTok, confirmVerb, confirmDanger, confirmLabel, canRun, askOp, cancelOp, runOp } = useOpConfirm(async p => {
|
|
43
|
+
const payload = p.to ? { operation: p.operation, confirm: p.apiConfirm, to: p.to } : { operation: p.operation, confirm: p.apiConfirm }
|
|
44
|
+
const res = await fetch('/api/server/operations/run', { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify(payload) })
|
|
45
|
+
const body = await res.json()
|
|
46
|
+
return (body.ok ? 'OK ' : 'FAILED ') + (body.command || p.operation) + '\n\n' + (body.stdout || '') + (body.stderr ? '\n' + body.stderr : '') + (body.error ? '\n' + body.error : '')
|
|
47
|
+
})
|
|
50
48
|
</script>
|
|
51
49
|
<!DOCTYPE html>
|
|
52
50
|
<html lang="en" data-theme="dark">
|
|
@@ -74,13 +72,13 @@ async function runOp() {
|
|
|
74
72
|
</div>
|
|
75
73
|
<div class="filters">
|
|
76
74
|
<div class="segmented" role="group" aria-label="Filter deployment status">
|
|
77
|
-
<button type="button" :class="{ active: status() === 'all' }" @click="
|
|
78
|
-
<button type="button" :class="{ active: status() === 'success' }" @click="
|
|
79
|
-
<button type="button" :class="{ active: status() === 'failed' }" @click="
|
|
75
|
+
<button type="button" :class="{ active: status() === 'all' }" @click="setFilter('status', 'all', status)">All</button>
|
|
76
|
+
<button type="button" :class="{ active: status() === 'success' }" @click="setFilter('status', 'success', status)">Success</button>
|
|
77
|
+
<button type="button" :class="{ active: status() === 'failed' }" @click="setFilter('status', 'failed', status)">Failed</button>
|
|
80
78
|
</div>
|
|
81
79
|
<label class="select-filter">
|
|
82
80
|
<span>Site</span>
|
|
83
|
-
<select :value="site()" @change="site
|
|
81
|
+
<select :value="site()" @change="setFilter('site', $event.target.value, site)">
|
|
84
82
|
<option value="all">All sites</option>
|
|
85
83
|
<template :for="s in sites()">
|
|
86
84
|
<option :value="s">{{ s }}</option>
|
|
@@ -89,7 +87,7 @@ async function runOp() {
|
|
|
89
87
|
</label>
|
|
90
88
|
</div>
|
|
91
89
|
<table>
|
|
92
|
-
<thead><tr><th>Build</th><th>Site</th><th>Branch</th><th>Status</th><th>Steps</th><th>By</th><th>Took</th><th>When</th><th>Action</th></tr></thead>
|
|
90
|
+
<thead><tr><th scope="col">Build</th><th scope="col">Site</th><th scope="col">Branch</th><th scope="col">Status</th><th scope="col">Steps</th><th scope="col">By</th><th scope="col">Took</th><th scope="col">When</th><th scope="col">Action</th></tr></thead>
|
|
93
91
|
<tbody>
|
|
94
92
|
<template :for="d in filtered()">
|
|
95
93
|
<tr>
|
|
@@ -101,7 +99,7 @@ async function runOp() {
|
|
|
101
99
|
<td style="color:var(--txt2)">{{ d.by }}</td>
|
|
102
100
|
<td class="mono">{{ d.took }}</td>
|
|
103
101
|
<td style="color:var(--txt3)">{{ d.when }}</td>
|
|
104
|
-
<td class="table-actions"
|
|
102
|
+
<td class="table-actions">@if (canRollback)<button class="btn danger sm" type="button" :aria-label="'Roll back ' + d.site + ' deployment ' + d.sha" @click="askOp('rollback:' + d.site, d.site, 'roll back', d.release)">Roll back</button>@else<span class="mono">read only</span>@endif</td>
|
|
105
103
|
</tr>
|
|
106
104
|
</template>
|
|
107
105
|
</tbody>
|
|
@@ -110,7 +108,7 @@ async function runOp() {
|
|
|
110
108
|
<div class="compact empty" @show="deps().length > 0 && filtered().length === 0"><strong>No matches</strong><span>Try a different status or site filter.</span></div>
|
|
111
109
|
@include('../partials/op-confirm')
|
|
112
110
|
@if (isMember)
|
|
113
|
-
<p class="note">
|
|
111
|
+
<p class="note">Deployment history is visible in this scope. Rollback requires an organization administrator because it changes server-wide release state.</p>
|
|
114
112
|
@else
|
|
115
113
|
<p class="note">Roll back a site to any prior release, or inspect a box with <span class="mono">cloud server:logs {{ server.name }}</span>.</p>
|
|
116
114
|
@endif
|
|
@@ -6,6 +6,9 @@ const initialAlwaysOpen = __d?.firewall?.alwaysOpen ?? [22, 80, 443]
|
|
|
6
6
|
const initialPorts = __d?.firewall?.ports ?? [8080, 6379]
|
|
7
7
|
</script>
|
|
8
8
|
<script client>
|
|
9
|
+
import { useOpConfirm } from '../../functions/useOpConfirm.ts'
|
|
10
|
+
import { requestJson } from '../../functions/requestJson.ts'
|
|
11
|
+
|
|
9
12
|
// Reactive host firewall (UFW) management - list + allow + remove, via signals +
|
|
10
13
|
// directives. Seeded from build-time data (stx server→client bridge); load()
|
|
11
14
|
// reconciles against the live cloud config, and each mutation applies UFW live.
|
|
@@ -31,36 +34,33 @@ async function load() {
|
|
|
31
34
|
} catch (e) { setMessage((e && e.message) || 'Could not read firewall config.', 'bad') }
|
|
32
35
|
}
|
|
33
36
|
async function allowPort() {
|
|
37
|
+
if (busy()) return
|
|
34
38
|
const port = Number(newPort())
|
|
35
39
|
if (!Number.isInteger(port) || port < 1 || port > 65535) { setMessage('Port must be a whole number between 1 and 65535.', 'bad'); return }
|
|
36
40
|
if (reserved.includes(port)) { setMessage('Ports 22, 80, and 443 are always open, so there is nothing to add.', 'bad'); return }
|
|
37
|
-
setMessage('Allowing port ' + port + '...', '')
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
41
|
+
busy.set(true); setMessage('Allowing port ' + port + '...', '')
|
|
42
|
+
try {
|
|
43
|
+
const data = await requestJson('/api/firewall', { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ port }) })
|
|
44
|
+
ports.set(data.ports || []); newPort.set('')
|
|
45
|
+
setMessage('Allowed port ' + port + ' in cloud config.' + applyLine(data.apply), 'ok')
|
|
46
|
+
} catch (error) { setMessage(error?.message || 'Could not allow port.', 'bad') }
|
|
47
|
+
finally { busy.set(false) }
|
|
43
48
|
}
|
|
44
49
|
async function removePort(port) {
|
|
45
50
|
setMessage('Removing port ' + port + '...', '')
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
+
try {
|
|
52
|
+
const data = await requestJson('/api/firewall', { method: 'DELETE', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ port }) })
|
|
53
|
+
ports.set(data.ports || [])
|
|
54
|
+
setMessage('Removed port ' + port + ' from cloud config.' + applyLine(data.apply), 'ok')
|
|
55
|
+
} catch (error) { setMessage(error?.message || 'Could not remove port.', 'bad') }
|
|
51
56
|
}
|
|
52
57
|
|
|
53
|
-
// Remove runs through
|
|
54
|
-
const
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
function
|
|
59
|
-
async function runRemove() {
|
|
60
|
-
const p = pending(); if (p === null || typed() !== String(p)) return
|
|
61
|
-
pending.set(null); typed.set('')
|
|
62
|
-
await removePort(p)
|
|
63
|
-
}
|
|
58
|
+
// Remove runs through the shared typed-confirm lifecycle.
|
|
59
|
+
const { opOutput, opShown, pending, typed, busy, confirmTok, confirmVerb, confirmDanger, confirmLabel, canRun, askOp, cancelOp, runOp } = useOpConfirm(async p => {
|
|
60
|
+
await removePort(Number(p.port))
|
|
61
|
+
return message()
|
|
62
|
+
})
|
|
63
|
+
function askRemove(port) { askOp('firewall:remove:' + port, String(port), 'remove port ' + port, null, String(port), { port, danger: true, label: 'Remove port' }) }
|
|
64
64
|
onMount(() => { load() })
|
|
65
65
|
</script>
|
|
66
66
|
<!DOCTYPE html>
|
|
@@ -100,7 +100,7 @@ onMount(() => { load() })
|
|
|
100
100
|
<input id="fw-port" type="number" min="1" max="65535" autocomplete="off" placeholder="8080" :value="newPort()" @input="newPort.set($event.target.value)" required>
|
|
101
101
|
</div>
|
|
102
102
|
<div class="form-actions">
|
|
103
|
-
<button class="btn" type="submit">Allow</button>
|
|
103
|
+
<button class="btn" type="submit" :disabled="busy()">Allow</button>
|
|
104
104
|
<span class="msg" :class="messageKind()" role="status">{{ message() }}</span>
|
|
105
105
|
</div>
|
|
106
106
|
</form>
|
|
@@ -113,19 +113,14 @@ onMount(() => { load() })
|
|
|
113
113
|
<div class="port-grid" @show="ports().length > 0">
|
|
114
114
|
<template :for="p in ports()">
|
|
115
115
|
<div class="port-card">
|
|
116
|
-
<div class="top"><span class="tag">tcp</span><button type="button" class="btn danger sm" @click="askRemove(p)">Remove</button></div>
|
|
116
|
+
<div class="top"><span class="tag">tcp</span><button type="button" class="btn danger sm" :aria-label="'Remove firewall port ' + p" @click="askRemove(p)">Remove</button></div>
|
|
117
117
|
<div class="listen mono">{{ p }}</div>
|
|
118
118
|
<div class="proc">Allowed via cloud config</div>
|
|
119
119
|
</div>
|
|
120
120
|
</template>
|
|
121
121
|
</div>
|
|
122
122
|
<div class="compact empty" @show="ports().length === 0"><strong>No extra ports configured</strong><span>Only 22, 80, and 443 are open. Allow a port above to update <span class="mono">infrastructure.compute.firewall</span>.</span></div>
|
|
123
|
-
|
|
124
|
-
<span>Type <b class="mono">{{ confirmTok() }}</b> to remove this port:</span>
|
|
125
|
-
<input class="op-confirm-input" :value="typed()" @input="typed.set($event.target.value)" @keydown.enter="runRemove()" placeholder="confirm" autocomplete="off">
|
|
126
|
-
<button class="btn sm" :disabled="!canRun()" @click="runRemove()">Run</button>
|
|
127
|
-
<button class="btn ghost sm" @click="cancelRemove()">Cancel</button>
|
|
128
|
-
</div>
|
|
123
|
+
@include('../partials/op-confirm')
|
|
129
124
|
<p class="note">Ports are declarative: this page edits <span class="mono">infrastructure.compute.firewall</span> in cloud config and applies <span class="mono">ufw allow</span> / <span class="mono">ufw delete allow</span> live on the box. The full config is reconciled again on the next <span class="mono">cloud deploy</span>.</p>
|
|
130
125
|
</div>
|
|
131
126
|
</div>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
<script client>
|
|
2
|
+
import { usePolling } from '../../functions/usePolling.ts'
|
|
3
|
+
const servers=state([]),operations=state([]),selected=state(null),search=state(''),notice=state(''),error=state(''),busy=state(false),adding=state(false)
|
|
4
|
+
async function api(url,options){const response=await fetch(url,options),body=await response.json();if(!response.ok||body.ok===false)throw new Error(body.error||'Request failed.');return body}async function load(){const data=await api('/api/fleet');servers.set(data.servers||[]);operations.set(data.operations||[]);if(selected())selected.set((data.servers||[]).find(v=>v.id===selected().id)||null)}const{pollingState,pollingError,lastUpdatedAt,refresh}=usePolling(load,15000)
|
|
5
|
+
async function mutate(url,value){busy.set(true);error.set('');try{const result=await api(url,{method:'POST',headers:{'content-type':'application/json'},body:JSON.stringify(value)});notice.set(result.operation?`Queued ${result.operation.id}.`:'Fleet state updated.');await refresh();return result}catch(cause){error.set(cause.message)}finally{busy.set(false)}}async function add(event){event.preventDefault();const value=Object.fromEntries(new FormData(event.currentTarget));value.roles=String(value.roles||'application').split(',').map(v=>v.trim()).filter(Boolean);value.labels=Object.fromEntries(String(value.labels||'').split(',').map(v=>v.split('=')).filter(v=>v[0]&&v[1]));const result=await mutate('/api/fleet',value);if(result){event.currentTarget.reset();adding.set(false);selected.set(result.server)}}async function action(name,extra={}){if(selected())await mutate('/api/fleet/action',{id:selected().id,action:name,...extra})}async function archive(){const name=prompt(`Type ${selected().name} to archive it without terminating provider infrastructure.`);if(name===selected().name)await action('archive',{confirmation:name})}function filtered(){const q=search().toLowerCase();return servers().filter(v=>!q||`${v.name} ${v.provider} ${v.region} ${v.roles.join(' ')} ${Object.values(v.labels).join(' ')}`.toLowerCase().includes(q))}function tone(v){return v==='ready'?'ok':['degraded','unreachable'].includes(v)?'bad':'warn'}function bytes(v){return v==null?'—':`${(v/1073741824).toFixed(1)} GB`}
|
|
6
|
+
</script><!DOCTYPE html><html lang="en" data-theme="dark"><head>@include('../partials/head',{title:'ts-cloud · Fleet inventory'})</head><body>@include('../partials/nav',{active:'fleet',env:'production'})
|
|
7
|
+
<main class="fleet-wrap wrap" id="main-content"><div class="crumbs">Infrastructure <span class="sep">/</span> Fleet inventory</div><header class="page"><div><h1>Fleet inventory</h1><p>Provider-neutral server identity, trust, validation, capacity, roles, heartbeat, and maintenance state.</p></div><div class="header-actions"><span class="pill" :class="pollingState()==='live'?'ok':'warn'">{{ pollingState() }}</span><small>{{ lastUpdatedAt()?.toLocaleTimeString()||'connecting' }}</small><button class="btn sm" @click="adding.set(!adding())">{{ adding()?'Close':'Add server' }}</button></div></header><p class="notice" role="status" @show="!!notice()">{{ notice() }}</p><p class="bad notice" role="alert" @show="!!error()||!!pollingError()">{{ error()||pollingError() }}</p>
|
|
8
|
+
<section class="summary"><article class="panel"><b>Servers</b><strong>{{ servers().length }}</strong></article><article class="panel"><b>Ready</b><strong>{{ servers().filter(v=>v.status==='ready').length }}</strong></article><article class="panel"><b>Unreachable</b><strong>{{ servers().filter(v=>v.status==='unreachable').length }}</strong></article><article class="panel"><b>Draining</b><strong>{{ servers().filter(v=>['draining','drained'].includes(v.status)).length }}</strong></article></section>
|
|
9
|
+
<form class="add-server panel" @show="adding()" @submit="add($event)"><div class="wide"><h2>Provision or connect existing</h2><p class="note">Enrollment only records identity and trust inputs. It never mutates an existing host until a reviewed bootstrap plan is confirmed.</p></div><label>Name<input name="name" required pattern="[a-z0-9][a-z0-9-]{1,62}"></label><label>Provider<select name="provider"><option>aws</option><option>hetzner</option><option>ssh</option></select></label><label>Provider ID<input name="providerId" placeholder="i-… / server id / external id"></label><label>Region / zone<input name="region" placeholder="us-west-2"></label><label>Endpoint<input name="endpoint" required placeholder="server.example.com"></label><label>SSH user<input name="sshUser" value="deploy" required></label><label>Credential reference<input name="credentialRef" required value="secret://fleet/agent"></label><label>Roles<input name="roles" value="application" placeholder="application,build"></label><label class="wide">Labels<input name="labels" placeholder="pool=production,arch=arm64"></label><button class="btn wide" type="submit">Enroll without mutation</button></form>
|
|
10
|
+
<section class="filters panel"><input type="search" aria-label="Search fleet" placeholder="Search provider, region, role, or label" @input="search.set($event.currentTarget.value)"></section><div class="fleet-grid" :class="{detail:!!selected()}"><section class="server-cards"><template :for="item in filtered()"><article class="panel server-card"><div><span class="pill" :class="tone(item.status)">{{ item.status }}</span><span class="pill">{{ item.provider }}</span><h2>{{ item.name }}</h2><p>{{ item.endpoint }} · {{ item.region||'external' }}</p></div><div class="facts"><span>{{ item.roles.join(', ') }}</span><span>{{ item.capacity.cpu||0 }} CPU · {{ bytes(item.capacity.memoryBytes) }}</span><span>heartbeat {{ item.heartbeatAt||'never' }}</span><span>trust {{ item.trustState }}</span></div><button class="btn ghost sm" @click="selected.set(item)">Inspect</button></article></template></section><aside class="detail-panel panel" @show="!!selected()"><div class="detail-head"><h2>{{ selected()?.name }}</h2><button class="btn ghost sm" @click="selected.set(null)">Close</button></div><div class="actions"><button class="btn sm" @click="action('test')">Test & pin key</button><button class="btn sm" @click="action('validate')" :disabled="selected()?.trustState!=='pinned'">Validate</button><button class="btn ghost sm" @click="action('bootstrap')">Preview bootstrap</button><button class="btn ghost sm" @click="action('bootstrap',{confirmed:true})" :disabled="!selected()?.validation?.valid">Apply bootstrap</button><button class="btn ghost sm" @click="action('drain')">Drain</button><button class="btn ghost sm" @click="action('uncordon')">Uncordon</button><button class="btn danger sm" @click="archive()">Archive only</button></div><p class="notice warn" @show="selected()?.trustState==='rotation_pending'">Host key changed. Review <code>{{ selected()?.pendingHostKey }}</code> before continuing. <button class="btn sm" @click="action('review_host_key',{fingerprint:selected().pendingHostKey})">Accept rotation</button></p><section><h3>Validation</h3><template :for="finding in selected()?.validation?.findings||[]"><p class="finding" :class="finding.severity==='error'?'bad-text':''"><b>{{ finding.code }}</b> {{ finding.message }}<small>{{ finding.remediation }}</small></p></template><pre>{{ JSON.stringify(selected()?.validation?.facts||{},null,2) }}</pre></section></aside></div></main><style>.fleet-wrap{padding-bottom:5rem}.header-actions,.actions{display:flex;gap:.5rem;flex-wrap:wrap;align-items:center}.summary{display:grid;grid-template-columns:repeat(4,1fr);gap:1rem;margin:1rem 0}.summary article{display:grid;gap:.4rem}.summary strong{font-size:1.8rem}.add-server{display:grid;grid-template-columns:repeat(2,1fr);gap:1rem}.add-server label{display:grid;gap:.3rem}.wide{grid-column:1/-1}.filters{margin:1rem 0}.filters input{width:100%}.fleet-grid.detail{display:grid;grid-template-columns:1fr 430px;gap:1rem}.server-cards{display:grid;gap:1rem}.server-card{display:grid;grid-template-columns:1fr 1fr auto;gap:1rem;align-items:center}.facts{display:grid;gap:.35rem}.detail-panel{position:sticky;top:1rem;align-self:start}.detail-head{display:flex;justify-content:space-between}.finding{display:grid;border-bottom:1px solid var(--border);padding:.5rem 0}.bad-text{color:var(--danger)}pre{white-space:pre-wrap;max-height:20rem;overflow:auto}@media(max-width:900px){.fleet-grid.detail{grid-template-columns:1fr}.detail-panel{position:static}.server-card{grid-template-columns:1fr}.summary{grid-template-columns:repeat(2,1fr)}}@media(max-width:560px){.add-server,.summary{grid-template-columns:1fr}.wide{grid-column:auto}}</style></body></html>
|
|
@@ -9,6 +9,8 @@ const initialLogs = __d?.serverLogs ?? []
|
|
|
9
9
|
const emptyReason = __d?.serverLogsEmptyReason ?? 'No server logs are available yet.'
|
|
10
10
|
</script>
|
|
11
11
|
<script client>
|
|
12
|
+
import { usePolling } from '../../functions/usePolling.ts'
|
|
13
|
+
|
|
12
14
|
// Reactive log viewer: seeded from build-time data (stx server→client bridge),
|
|
13
15
|
// then filters by level + source and auto-refreshes - all via signals +
|
|
14
16
|
// directives (no manual DOM).
|
|
@@ -19,15 +21,13 @@ const sources = derived(() => [...new Set(logs().map(l => l.source).filter(Boole
|
|
|
19
21
|
const filtered = derived(() => logs().filter(l =>
|
|
20
22
|
(level() === 'all' || l.level === level()) && (source() === 'all' || l.source === source())))
|
|
21
23
|
function tone(l) { return l === 'error' ? 'bad' : (l === 'warn' ? 'warn' : 'ok') }
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
}
|
|
30
|
-
onMount(() => { refresh(); const id = setInterval(refresh, 8000); return () => clearInterval(id) })
|
|
24
|
+
const { pollingState, pollingError, pollingLabel } = usePolling(async () => {
|
|
25
|
+
const res = await fetch('/api/dashboard-data')
|
|
26
|
+
if (!res.ok) throw new Error('Log refresh failed with HTTP ' + res.status + '.')
|
|
27
|
+
const data = await res.json()
|
|
28
|
+
if (!Array.isArray(data.serverLogs)) throw new Error('Log refresh returned an invalid payload.')
|
|
29
|
+
logs.set(data.serverLogs)
|
|
30
|
+
}, 8000)
|
|
31
31
|
</script>
|
|
32
32
|
<!DOCTYPE html>
|
|
33
33
|
<html lang="en" data-theme="dark">
|
|
@@ -53,6 +53,7 @@ onMount(() => { refresh(); const id = setInterval(refresh, 8000); return () => c
|
|
|
53
53
|
</div>
|
|
54
54
|
<div class="cmds header-actions"><span class="accent cmd">cloud server:logs {{ server.name }}</span></div>
|
|
55
55
|
@endif
|
|
56
|
+
<div class="header-actions"><span class="pill" :class="{ ok: pollingState() === 'live', warn: pollingState() !== 'live' }">{{ pollingLabel() }}</span></div>
|
|
56
57
|
</header>
|
|
57
58
|
|
|
58
59
|
<div class="section">
|
|
@@ -89,6 +90,7 @@ onMount(() => { refresh(); const id = setInterval(refresh, 8000); return () => c
|
|
|
89
90
|
</div>
|
|
90
91
|
<div class="compact empty" @show="logs().length > 0 && filtered().length === 0"><strong>No matching logs</strong><span>Try a different level or source filter.</span></div>
|
|
91
92
|
<div class="empty" @show="logs().length === 0"><strong>No logs available</strong><span>{{ emptyReason }}</span></div>
|
|
93
|
+
<p class="bad note" role="status" @show="pollingState() === 'stale'">Showing the last successful snapshot. {{ pollingError() }}</p>
|
|
92
94
|
|
|
93
95
|
@if (isMember)
|
|
94
96
|
<p class="note">Live <span class="mono">journalctl</span> for your sites' services, <b>queue workers</b> and daemons. Auto-refreshes every 8s.</p>
|
|
@@ -3,20 +3,13 @@ import { renderResourceBars } from '../../src/charts.ts'
|
|
|
3
3
|
|
|
4
4
|
// ts-cloud server health view. Real data is injected at build time via
|
|
5
5
|
// TSCLOUD_DASHBOARD_DATA (see deploy/dashboard-data-server.ts); the sample
|
|
6
|
-
//
|
|
6
|
+
// No fallback samples: missing data must remain visibly unavailable.
|
|
7
7
|
let __d = null
|
|
8
8
|
try { __d = JSON.parse(process.env.TSCLOUD_DASHBOARD_DATA || '') } catch { __d = null }
|
|
9
9
|
|
|
10
|
-
const server = __d?.server ?? {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
}
|
|
14
|
-
const m = __d?.systemMetrics ?? {
|
|
15
|
-
load: 0.42, cpus: 4,
|
|
16
|
-
memUsedMb: 2480, memTotalMb: 7860,
|
|
17
|
-
diskUsedPct: 38, diskUsedGb: 19, diskTotalGb: 50,
|
|
18
|
-
}
|
|
19
|
-
const live = __d ? !!__d?._serverReachable && !__d?.metricsUnavailable : true
|
|
10
|
+
const server = __d?.server ?? { name: 'Server', provider: 'unavailable', region: 'unavailable', os: 'unavailable', uptime: 'unavailable' }
|
|
11
|
+
const m = __d?.systemMetrics ?? { load: 0, cpus: 0, memUsedMb: 0, memTotalMb: 0, diskUsedPct: 0, diskUsedGb: 0, diskTotalGb: 0 }
|
|
12
|
+
const live = !!__d && !!__d?._serverReachable && !__d?.metricsUnavailable
|
|
20
13
|
|
|
21
14
|
// ── Derived percentages ───────────────────────────────────────────────
|
|
22
15
|
const memPct = live ? Math.min(100, Math.round((m.memUsedMb / Math.max(1, m.memTotalMb)) * 100)) : 0
|
|
@@ -63,10 +56,9 @@ const resourceChart = renderResourceBars([
|
|
|
63
56
|
{ label: 'Disk', value: diskPct, detail: live ? `${m.diskUsedGb} / ${m.diskTotalGb} GB` : unavailableNote },
|
|
64
57
|
], { disabled: !live })
|
|
65
58
|
|
|
66
|
-
|
|
67
|
-
const loadTrend = __d?.loadTrend ?? [22, 28, 31, 26, 40, 38, 33, 45, 41, 30, 27, 35, 48, 52, 39, 33, 29, 44, 50, 47, 36, 31, 28, 34]
|
|
59
|
+
const loadTrend = __d?.loadTrend ?? []
|
|
68
60
|
const maxLoad = Math.max(...loadTrend, 1)
|
|
69
|
-
const trendPeak = Math.max(...loadTrend)
|
|
61
|
+
const trendPeak = loadTrend.length ? Math.max(...loadTrend) : 0
|
|
70
62
|
function barPct(v) { return Math.round((v / maxLoad) * 100) }
|
|
71
63
|
function barTone(v) { const r = v / maxLoad; return r >= 0.9 ? 'peak' : r >= 0.7 ? 'hot' : '' }
|
|
72
64
|
</script>
|
|
@@ -165,7 +157,7 @@ function barTone(v) { const r = v / maxLoad; return r >= 0.9 ? 'peak' : r >= 0.7
|
|
|
165
157
|
<div class="section">
|
|
166
158
|
<h2>CPU load trend</h2>
|
|
167
159
|
<div class="chart panel">
|
|
168
|
-
@if (live)
|
|
160
|
+
@if (live && loadTrend.length)
|
|
169
161
|
<div class="spark">
|
|
170
162
|
@foreach (loadTrend as v)
|
|
171
163
|
<i class="{{ barTone(v) }}" style="height: {{ barPct(v) }}%"></i>
|
|
@@ -174,7 +166,7 @@ function barTone(v) { const r = v / maxLoad; return r >= 0.9 ? 'peak' : r >= 0.7
|
|
|
174
166
|
<div class="xaxis"><span>-24 snapshots</span><span>peak {{ trendPeak }}% · now</span></div>
|
|
175
167
|
<p class="note">% of CPU capacity · refresh with <span class="mono">cloud server:monitoring {{ server.name }}</span></p>
|
|
176
168
|
@else
|
|
177
|
-
<div class="compact empty"><strong>No
|
|
169
|
+
<div class="compact empty"><strong>No historical trend</strong><span>Open <a href="/operations/observability">Observability</a> for persisted host metrics, source freshness, timezone, and gaps.</span></div>
|
|
178
170
|
@endif
|
|
179
171
|
</div>
|
|
180
172
|
</div>
|
|
@@ -12,29 +12,16 @@ const services = __d?.servicesDetail ?? [
|
|
|
12
12
|
function tone(s) { return s === 'running' ? 'ok' : (s === 'stopped' || s === 'failed' ? 'bad' : 'warn') }
|
|
13
13
|
</script>
|
|
14
14
|
<script client>
|
|
15
|
+
import { useOpConfirm } from '../../functions/useOpConfirm.ts'
|
|
16
|
+
|
|
15
17
|
// Reactive server-operation runner: a typed-confirmation bar + output, driven by
|
|
16
18
|
// signals + directives (no manual DOM). Buttons call askOp(...) to stage an op.
|
|
17
|
-
const opOutput =
|
|
18
|
-
const
|
|
19
|
-
const
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
const canRun = derived(() => { const p = pending(); return !!p && typed() === p.confirm })
|
|
24
|
-
function askOp(operation, confirm, verb, to) { pending.set({ operation, confirm, verb, to: to || null }); typed.set('') }
|
|
25
|
-
function cancelOp() { pending.set(null) }
|
|
26
|
-
async function runOp() {
|
|
27
|
-
const p = pending()
|
|
28
|
-
if (!p || typed() !== p.confirm) return
|
|
29
|
-
pending.set(null); typed.set('')
|
|
30
|
-
opShown.set(true); opOutput.set('Running ' + p.operation + '...')
|
|
31
|
-
try {
|
|
32
|
-
const payload = p.to ? { operation: p.operation, confirm: p.confirm, to: p.to } : { operation: p.operation, confirm: p.confirm }
|
|
33
|
-
const res = await fetch('/api/server/operations/run', { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify(payload) })
|
|
34
|
-
const body = await res.json()
|
|
35
|
-
opOutput.set((body.ok ? 'OK ' : 'FAILED ') + (body.command || p.operation) + '\n\n' + (body.stdout || '') + (body.stderr ? '\n' + body.stderr : '') + (body.error ? '\n' + body.error : ''))
|
|
36
|
-
} catch (e) { opOutput.set('FAILED ' + p.operation + '\n\n' + ((e && e.message) || e)) }
|
|
37
|
-
}
|
|
19
|
+
const { opOutput, opShown, pending, typed, busy, confirmTok, confirmVerb, confirmDanger, confirmLabel, canRun, askOp, cancelOp, runOp } = useOpConfirm(async p => {
|
|
20
|
+
const payload = p.to ? { operation: p.operation, confirm: p.apiConfirm, to: p.to } : { operation: p.operation, confirm: p.apiConfirm }
|
|
21
|
+
const res = await fetch('/api/server/operations/run', { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify(payload) })
|
|
22
|
+
const body = await res.json()
|
|
23
|
+
return (body.ok ? 'OK ' : 'FAILED ') + (body.command || p.operation) + '\n\n' + (body.stdout || '') + (body.stderr ? '\n' + body.stderr : '') + (body.error ? '\n' + body.error : '')
|
|
24
|
+
})
|
|
38
25
|
</script>
|
|
39
26
|
<!DOCTYPE html>
|
|
40
27
|
<html lang="en" data-theme="dark">
|
|
@@ -49,8 +36,9 @@ async function runOp() {
|
|
|
49
36
|
</header>
|
|
50
37
|
<div class="section">
|
|
51
38
|
<div class="panel">
|
|
39
|
+
@if (services.length)
|
|
52
40
|
<table>
|
|
53
|
-
<thead><tr><th>Service</th><th>Status</th><th>Uptime</th><th>Memory</th><th>Autostart</th><th>Manage</th></tr></thead>
|
|
41
|
+
<thead><tr><th scope="col">Service</th><th scope="col">Status</th><th scope="col">Uptime</th><th scope="col">Memory</th><th scope="col">Autostart</th><th scope="col">Manage</th></tr></thead>
|
|
54
42
|
<tbody>
|
|
55
43
|
@foreach (services as s)
|
|
56
44
|
<tr>
|
|
@@ -61,18 +49,21 @@ async function runOp() {
|
|
|
61
49
|
<td>@if (s.auto)<span class="ok pill">enabled</span>@else<span class="pill warn">disabled</span>@endif</td>
|
|
62
50
|
<td>
|
|
63
51
|
<div class="action-runner">
|
|
64
|
-
<button class="btn ghost sm" type="button" @click="askOp('restart:{{ s.name }}', '{{ s.name }}', 'restart')">Restart</button>
|
|
65
|
-
<button class="btn ghost sm" type="button" @click="askOp('reload:{{ s.name }}', '{{ s.name }}', 'reload')">Reload</button>
|
|
66
|
-
<button class="btn ghost sm" type="button" @click="askOp('start:{{ s.name }}', '{{ s.name }}', 'start')">Start</button>
|
|
67
|
-
<button class="btn danger sm" type="button" @click="askOp('stop:{{ s.name }}', '{{ s.name }}', 'stop')">Stop</button>
|
|
68
|
-
<button class="btn ghost sm" type="button" @click="askOp('enable:{{ s.name }}', '{{ s.name }}', 'enable')">Enable</button>
|
|
69
|
-
<button class="btn ghost sm" type="button" @click="askOp('disable:{{ s.name }}', '{{ s.name }}', 'disable')">Disable</button>
|
|
52
|
+
<button class="btn ghost sm" type="button" aria-label="Restart {{ s.name }}" @click="askOp('restart:{{ s.name }}', 'restart {{ s.name }}', 'restart {{ s.name }}', null, '{{ s.name }}')">Restart</button>
|
|
53
|
+
<button class="btn ghost sm" type="button" aria-label="Reload {{ s.name }}" @click="askOp('reload:{{ s.name }}', 'reload {{ s.name }}', 'reload {{ s.name }}', null, '{{ s.name }}')">Reload</button>
|
|
54
|
+
<button class="btn ghost sm" type="button" aria-label="Start {{ s.name }}" @click="askOp('start:{{ s.name }}', 'start {{ s.name }}', 'start {{ s.name }}', null, '{{ s.name }}')">Start</button>
|
|
55
|
+
<button class="btn danger sm" type="button" aria-label="Stop {{ s.name }}" @click="askOp('stop:{{ s.name }}', 'stop {{ s.name }}', 'stop {{ s.name }}', null, '{{ s.name }}')">Stop</button>
|
|
56
|
+
<button class="btn ghost sm" type="button" aria-label="Enable {{ s.name }}" @click="askOp('enable:{{ s.name }}', 'enable {{ s.name }}', 'enable {{ s.name }}', null, '{{ s.name }}')">Enable</button>
|
|
57
|
+
<button class="btn ghost sm" type="button" aria-label="Disable {{ s.name }}" @click="askOp('disable:{{ s.name }}', 'disable {{ s.name }}', 'disable {{ s.name }}', null, '{{ s.name }}')">Disable</button>
|
|
70
58
|
</div>
|
|
71
59
|
</td>
|
|
72
60
|
</tr>
|
|
73
61
|
@endforeach
|
|
74
62
|
</tbody>
|
|
75
63
|
</table>
|
|
64
|
+
@else
|
|
65
|
+
<div class="empty"><strong>No managed services</strong><span>Services appear here after they are configured and discovered on the server.</span></div>
|
|
66
|
+
@endif
|
|
76
67
|
@include('../partials/op-confirm')
|
|
77
68
|
<p class="note">Install software with <span class="mono">cloud server:recipe {{ server.name }} <recipe></span>.</p>
|
|
78
69
|
</div>
|