mcpmake 0.1.1 → 0.2.1
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/README.md +88 -635
- package/dist/commands/bundle.d.ts +1 -0
- package/dist/commands/bundle.d.ts.map +1 -0
- package/dist/commands/bundle.js +5 -4
- package/dist/commands/bundle.js.map +1 -0
- package/dist/commands/ci.d.ts +1 -0
- package/dist/commands/ci.d.ts.map +1 -0
- package/dist/commands/ci.js +3 -2
- package/dist/commands/ci.js.map +1 -0
- package/dist/commands/deploy.d.ts +1 -0
- package/dist/commands/deploy.d.ts.map +1 -0
- package/dist/commands/deploy.js +4 -3
- package/dist/commands/deploy.js.map +1 -0
- package/dist/commands/diff.d.ts +1 -0
- package/dist/commands/diff.d.ts.map +1 -0
- package/dist/commands/diff.js +5 -4
- package/dist/commands/diff.js.map +1 -0
- package/dist/commands/from/describe.d.ts +1 -0
- package/dist/commands/from/describe.d.ts.map +1 -0
- package/dist/commands/from/describe.js +11 -10
- package/dist/commands/from/describe.js.map +1 -0
- package/dist/commands/from/har.d.ts +1 -0
- package/dist/commands/from/har.d.ts.map +1 -0
- package/dist/commands/from/har.js +14 -13
- package/dist/commands/from/har.js.map +1 -0
- package/dist/commands/from/openapi.d.ts +1 -0
- package/dist/commands/from/openapi.d.ts.map +1 -0
- package/dist/commands/from/openapi.js +17 -16
- package/dist/commands/from/openapi.js.map +1 -0
- package/dist/commands/from/postman.d.ts +1 -0
- package/dist/commands/from/postman.d.ts.map +1 -0
- package/dist/commands/from/postman.js +13 -12
- package/dist/commands/from/postman.js.map +1 -0
- package/dist/commands/from/stainless.d.ts +110 -0
- package/dist/commands/from/stainless.d.ts.map +1 -0
- package/dist/commands/from/stainless.js +272 -0
- package/dist/commands/from/stainless.js.map +1 -0
- package/dist/commands/from/target-support.d.ts +1 -0
- package/dist/commands/from/target-support.d.ts.map +1 -0
- package/dist/commands/from/target-support.js +2 -1
- package/dist/commands/from/target-support.js.map +1 -0
- package/dist/commands/from/url.d.ts +1 -0
- package/dist/commands/from/url.d.ts.map +1 -0
- package/dist/commands/from/url.js +14 -13
- package/dist/commands/from/url.js.map +1 -0
- package/dist/commands/from/website.d.ts +1 -0
- package/dist/commands/from/website.d.ts.map +1 -0
- package/dist/commands/from/website.js +17 -16
- package/dist/commands/from/website.js.map +1 -0
- package/dist/commands/lint.d.ts +1 -0
- package/dist/commands/lint.d.ts.map +1 -0
- package/dist/commands/lint.js +6 -5
- package/dist/commands/lint.js.map +1 -0
- package/dist/commands/merge.d.ts +1 -0
- package/dist/commands/merge.d.ts.map +1 -0
- package/dist/commands/merge.js +3 -2
- package/dist/commands/merge.js.map +1 -0
- package/dist/commands/publish.d.ts +1 -0
- package/dist/commands/publish.d.ts.map +1 -0
- package/dist/commands/publish.js +4 -3
- package/dist/commands/publish.js.map +1 -0
- package/dist/commands/rescan.d.ts +1 -0
- package/dist/commands/rescan.d.ts.map +1 -0
- package/dist/commands/rescan.js +12 -11
- package/dist/commands/rescan.js.map +1 -0
- package/dist/commands/update.d.ts +1 -0
- package/dist/commands/update.d.ts.map +1 -0
- package/dist/commands/update.js +10 -9
- package/dist/commands/update.js.map +1 -0
- package/dist/commands/verify.d.ts +1 -0
- package/dist/commands/verify.d.ts.map +1 -0
- package/dist/commands/verify.js +7 -6
- package/dist/commands/verify.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +23 -2
- package/dist/index.js.map +1 -0
- package/dist/registry/official-registry.d.ts +1 -0
- package/dist/registry/official-registry.d.ts.map +1 -0
- package/dist/registry/official-registry.js +1 -0
- package/dist/registry/official-registry.js.map +1 -0
- package/package.json +20 -46
- package/dist/analyzer/auth-detector.d.ts +0 -12
- package/dist/analyzer/auth-detector.js +0 -142
- package/dist/analyzer/dom-parser.d.ts +0 -10
- package/dist/analyzer/dom-parser.js +0 -259
- package/dist/analyzer/goal-crawler.d.ts +0 -25
- package/dist/analyzer/goal-crawler.js +0 -177
- package/dist/analyzer/hybrid-detector.d.ts +0 -28
- package/dist/analyzer/hybrid-detector.js +0 -96
- package/dist/analyzer/index.d.ts +0 -12
- package/dist/analyzer/index.js +0 -8
- package/dist/analyzer/screenshot-capture.d.ts +0 -29
- package/dist/analyzer/screenshot-capture.js +0 -42
- package/dist/analyzer/selector-builder.d.ts +0 -19
- package/dist/analyzer/selector-builder.js +0 -199
- package/dist/analyzer/semantic-analyzer.d.ts +0 -13
- package/dist/analyzer/semantic-analyzer.js +0 -145
- package/dist/analyzer/site-crawler.d.ts +0 -38
- package/dist/analyzer/site-crawler.js +0 -235
- package/dist/cloud/billing/billing-engine.d.ts +0 -44
- package/dist/cloud/billing/billing-engine.js +0 -81
- package/dist/cloud/billing/credit-store.d.ts +0 -64
- package/dist/cloud/billing/credit-store.js +0 -168
- package/dist/cloud/billing/index.d.ts +0 -4
- package/dist/cloud/billing/index.js +0 -2
- package/dist/cloud/billing/usage-store.d.ts +0 -42
- package/dist/cloud/billing/usage-store.js +0 -85
- package/dist/cloud/billing/usage-tracker.d.ts +0 -38
- package/dist/cloud/billing/usage-tracker.js +0 -95
- package/dist/cloud/build-pipeline.d.ts +0 -39
- package/dist/cloud/build-pipeline.js +0 -310
- package/dist/cloud/build-queue.d.ts +0 -30
- package/dist/cloud/build-queue.js +0 -70
- package/dist/cloud/caddy-manager.d.ts +0 -18
- package/dist/cloud/caddy-manager.js +0 -97
- package/dist/cloud/container-backend.d.ts +0 -62
- package/dist/cloud/container-backend.js +0 -59
- package/dist/cloud/container-manager.d.ts +0 -64
- package/dist/cloud/container-manager.js +0 -301
- package/dist/cloud/crypto.d.ts +0 -27
- package/dist/cloud/crypto.js +0 -63
- package/dist/cloud/db/index.d.ts +0 -27
- package/dist/cloud/db/index.js +0 -53
- package/dist/cloud/db/migrations.d.ts +0 -12
- package/dist/cloud/db/migrations.js +0 -329
- package/dist/cloud/db/pg-store.d.ts +0 -45
- package/dist/cloud/db/pg-store.js +0 -336
- package/dist/cloud/failure-tracker.d.ts +0 -51
- package/dist/cloud/failure-tracker.js +0 -102
- package/dist/cloud/idle-monitor.d.ts +0 -30
- package/dist/cloud/idle-monitor.js +0 -70
- package/dist/cloud/mailer.d.ts +0 -21
- package/dist/cloud/mailer.js +0 -193
- package/dist/cloud/mcp-proxy.d.ts +0 -58
- package/dist/cloud/mcp-proxy.js +0 -203
- package/dist/cloud/metric-samples.d.ts +0 -43
- package/dist/cloud/metric-samples.js +0 -85
- package/dist/cloud/metrics.d.ts +0 -26
- package/dist/cloud/metrics.js +0 -59
- package/dist/cloud/multipart.d.ts +0 -26
- package/dist/cloud/multipart.js +0 -132
- package/dist/cloud/observability.d.ts +0 -27
- package/dist/cloud/observability.js +0 -98
- package/dist/cloud/rate-limiter.d.ts +0 -31
- package/dist/cloud/rate-limiter.js +0 -58
- package/dist/cloud/request-security.d.ts +0 -5
- package/dist/cloud/request-security.js +0 -74
- package/dist/cloud/resource-monitor.d.ts +0 -69
- package/dist/cloud/resource-monitor.js +0 -130
- package/dist/cloud/secret-store.d.ts +0 -38
- package/dist/cloud/secret-store.js +0 -103
- package/dist/cloud/security.d.ts +0 -26
- package/dist/cloud/security.js +0 -142
- package/dist/cloud/server.d.ts +0 -21
- package/dist/cloud/server.js +0 -1079
- package/dist/cloud/shared-state.d.ts +0 -72
- package/dist/cloud/shared-state.js +0 -159
- package/dist/cloud/ssrf.d.ts +0 -43
- package/dist/cloud/ssrf.js +0 -150
- package/dist/cloud/store.d.ts +0 -41
- package/dist/cloud/store.js +0 -75
- package/dist/cloud/stripe.d.ts +0 -78
- package/dist/cloud/stripe.js +0 -317
- package/dist/cloud/telemetry-store.d.ts +0 -53
- package/dist/cloud/telemetry-store.js +0 -108
- package/dist/cloud/web/auth.d.ts +0 -225
- package/dist/cloud/web/auth.js +0 -555
- package/dist/cloud/web/charts.d.ts +0 -70
- package/dist/cloud/web/charts.js +0 -178
- package/dist/cloud/web/csrf.d.ts +0 -14
- package/dist/cloud/web/csrf.js +0 -22
- package/dist/cloud/web/docs.d.ts +0 -40
- package/dist/cloud/web/docs.js +0 -174
- package/dist/cloud/web/router.d.ts +0 -25
- package/dist/cloud/web/router.js +0 -1921
- package/dist/cloud/web/static/alpine.min.js +0 -5
- package/dist/cloud/web/static/favicon.svg +0 -4
- package/dist/cloud/web/static/htmx-sse.js +0 -290
- package/dist/cloud/web/static/htmx.min.js +0 -1
- package/dist/cloud/web/static/style.css +0 -2683
- package/dist/cloud/web/static-server.d.ts +0 -13
- package/dist/cloud/web/static-server.js +0 -73
- package/dist/cloud/web/template-engine.d.ts +0 -27
- package/dist/cloud/web/template-engine.js +0 -146
- package/dist/cloud/web/templates/layouts/admin.hbs +0 -57
- package/dist/cloud/web/templates/layouts/auth.hbs +0 -138
- package/dist/cloud/web/templates/layouts/base.hbs +0 -16
- package/dist/cloud/web/templates/layouts/dashboard.hbs +0 -39
- package/dist/cloud/web/templates/layouts/landing.hbs +0 -82
- package/dist/cloud/web/templates/pages/admin/overview.hbs +0 -123
- package/dist/cloud/web/templates/pages/admin/servers.hbs +0 -129
- package/dist/cloud/web/templates/pages/admin/telemetry.hbs +0 -39
- package/dist/cloud/web/templates/pages/admin/user-edit.hbs +0 -91
- package/dist/cloud/web/templates/pages/admin/users.hbs +0 -179
- package/dist/cloud/web/templates/pages/auth/forgot-password.hbs +0 -25
- package/dist/cloud/web/templates/pages/auth/login.hbs +0 -33
- package/dist/cloud/web/templates/pages/auth/register.hbs +0 -32
- package/dist/cloud/web/templates/pages/auth/reset-password.hbs +0 -34
- package/dist/cloud/web/templates/pages/dashboard/billing.hbs +0 -140
- package/dist/cloud/web/templates/pages/dashboard/create.hbs +0 -173
- package/dist/cloud/web/templates/pages/dashboard/index.hbs +0 -8
- package/dist/cloud/web/templates/pages/dashboard/server-detail.hbs +0 -280
- package/dist/cloud/web/templates/pages/dashboard/server-logs.hbs +0 -35
- package/dist/cloud/web/templates/pages/dashboard/server-metrics.hbs +0 -63
- package/dist/cloud/web/templates/pages/dashboard/servers-partial.hbs +0 -21
- package/dist/cloud/web/templates/pages/dashboard/servers.hbs +0 -44
- package/dist/cloud/web/templates/pages/docs/show.hbs +0 -16
- package/dist/cloud/web/templates/pages/errors/404.hbs +0 -9
- package/dist/cloud/web/templates/pages/errors/500.hbs +0 -8
- package/dist/cloud/web/templates/pages/landing/index.hbs +0 -223
- package/dist/cloud/web/templates/pages/legal/privacy.hbs +0 -71
- package/dist/cloud/web/templates/pages/legal/terms.hbs +0 -73
- package/dist/cloud/web/templates/partials/admin-stats.hbs +0 -52
- package/dist/cloud/web/templates/partials/flash-message.hbs +0 -6
- package/dist/cloud/web/templates/partials/pricing-table.hbs +0 -103
- package/dist/cloud/web/templates/partials/server-card.hbs +0 -19
- package/dist/cloud/web/templates/partials/status-badge.hbs +0 -1
- package/dist/config/configurable-command.d.ts +0 -13
- package/dist/config/configurable-command.js +0 -70
- package/dist/config/mcpmake-config.d.ts +0 -68
- package/dist/config/mcpmake-config.js +0 -207
- package/dist/docs/cli.md +0 -400
- package/dist/docs/mcp-2026-07-28-migration.md +0 -78
- package/dist/docs/migrate-from-stainless.md +0 -94
- package/dist/docs/quickstart.md +0 -166
- package/dist/docs/show-hn.md +0 -26
- package/dist/docs/website-servers.md +0 -169
- package/dist/emitter/code-writer.d.ts +0 -8
- package/dist/emitter/code-writer.js +0 -25
- package/dist/emitter/index.d.ts +0 -32
- package/dist/emitter/index.js +0 -280
- package/dist/emitter/mcpb-bundler.d.ts +0 -31
- package/dist/emitter/mcpb-bundler.js +0 -172
- package/dist/emitter/project-scaffolder.d.ts +0 -4
- package/dist/emitter/project-scaffolder.js +0 -89
- package/dist/emitter/python-template-loader.d.ts +0 -4
- package/dist/emitter/python-template-loader.js +0 -30
- package/dist/emitter/python-templates/dockerfile.hbs +0 -14
- package/dist/emitter/python-templates/env.example.hbs +0 -6
- package/dist/emitter/python-templates/requirements.txt.hbs +0 -4
- package/dist/emitter/python-templates/server.py.hbs +0 -77
- package/dist/emitter/site-scaffolder.d.ts +0 -13
- package/dist/emitter/site-scaffolder.js +0 -70
- package/dist/emitter/site-template-loader.d.ts +0 -5
- package/dist/emitter/site-template-loader.js +0 -47
- package/dist/emitter/site-templates/browser-manager.ts.hbs +0 -233
- package/dist/emitter/site-templates/config.ts.hbs +0 -28
- package/dist/emitter/site-templates/dockerfile.hbs +0 -31
- package/dist/emitter/site-templates/env.example.hbs +0 -19
- package/dist/emitter/site-templates/package.json.hbs +0 -26
- package/dist/emitter/site-templates/server-main-http.ts.hbs +0 -108
- package/dist/emitter/site-templates/server-main.ts.hbs +0 -23
- package/dist/emitter/site-templates/tool-handler-action.ts.hbs +0 -86
- package/dist/emitter/site-templates/tool-handler-form.ts.hbs +0 -116
- package/dist/emitter/site-templates/tool-handler-lifecycle.ts.hbs +0 -146
- package/dist/emitter/site-templates/tool-index.ts.hbs +0 -11
- package/dist/emitter/template-loader.d.ts +0 -1
- package/dist/emitter/template-loader.js +0 -27
- package/dist/emitter/templates/auth-provider.ts.hbs +0 -57
- package/dist/emitter/templates/config.ts.hbs +0 -63
- package/dist/emitter/templates/discovery.ts.hbs +0 -301
- package/dist/emitter/templates/dockerfile.hbs +0 -34
- package/dist/emitter/templates/env.example.hbs +0 -28
- package/dist/emitter/templates/gitignore.hbs +0 -5
- package/dist/emitter/templates/http-executor.ts.hbs +0 -117
- package/dist/emitter/templates/oauth.ts.hbs +0 -188
- package/dist/emitter/templates/package.json.hbs +0 -25
- package/dist/emitter/templates/prompts.ts.hbs +0 -22
- package/dist/emitter/templates/readme.md.hbs +0 -123
- package/dist/emitter/templates/resources.ts.hbs +0 -63
- package/dist/emitter/templates/server-main-http.ts.hbs +0 -407
- package/dist/emitter/templates/server-main.ts.hbs +0 -40
- package/dist/emitter/templates/task-handlers.ts.hbs +0 -189
- package/dist/emitter/templates/task-manager.ts.hbs +0 -139
- package/dist/emitter/templates/task-sse.ts.hbs +0 -105
- package/dist/emitter/templates/tool-handler.ts.hbs +0 -124
- package/dist/emitter/templates/tool-index.ts.hbs +0 -11
- package/dist/emitter/templates/tool-test.ts.hbs +0 -57
- package/dist/emitter/templates/trace.ts.hbs +0 -79
- package/dist/emitter/templates/tsconfig.json.hbs +0 -16
- package/dist/emitter/templates/types.ts.hbs +0 -5
- package/dist/emitter/worker-template-loader.d.ts +0 -5
- package/dist/emitter/worker-template-loader.js +0 -33
- package/dist/emitter/worker-templates/config.ts.hbs +0 -54
- package/dist/emitter/worker-templates/dev-vars.example.hbs +0 -10
- package/dist/emitter/worker-templates/gitignore.hbs +0 -6
- package/dist/emitter/worker-templates/package.json.hbs +0 -24
- package/dist/emitter/worker-templates/readme.md.hbs +0 -53
- package/dist/emitter/worker-templates/server.test.ts.hbs +0 -20
- package/dist/emitter/worker-templates/tool-handler.ts.hbs +0 -85
- package/dist/emitter/worker-templates/tool-index.ts.hbs +0 -28
- package/dist/emitter/worker-templates/tsconfig.json.hbs +0 -17
- package/dist/emitter/worker-templates/worker.ts.hbs +0 -242
- package/dist/emitter/worker-templates/wrangler.toml.hbs +0 -19
- package/dist/generator/spec-generator.d.ts +0 -6
- package/dist/generator/spec-generator.js +0 -50
- package/dist/parser/har-filter.d.ts +0 -8
- package/dist/parser/har-filter.js +0 -71
- package/dist/parser/har-loader.d.ts +0 -2
- package/dist/parser/har-loader.js +0 -14
- package/dist/parser/har-normalizer.d.ts +0 -20
- package/dist/parser/har-normalizer.js +0 -78
- package/dist/parser/index.d.ts +0 -10
- package/dist/parser/index.js +0 -6
- package/dist/parser/openapi-loader.d.ts +0 -6
- package/dist/parser/openapi-loader.js +0 -308
- package/dist/parser/operation-extractor.d.ts +0 -13
- package/dist/parser/operation-extractor.js +0 -155
- package/dist/parser/overlay-loader.d.ts +0 -10
- package/dist/parser/overlay-loader.js +0 -184
- package/dist/parser/postman-loader.d.ts +0 -9
- package/dist/parser/postman-loader.js +0 -106
- package/dist/parser/schema-converter.d.ts +0 -12
- package/dist/parser/schema-converter.js +0 -117
- package/dist/plugins/adapter.d.ts +0 -40
- package/dist/plugins/adapter.js +0 -15
- package/dist/plugins/loader.d.ts +0 -25
- package/dist/plugins/loader.js +0 -58
- package/dist/pricing.d.ts +0 -55
- package/dist/pricing.js +0 -133
- package/dist/providers/index.d.ts +0 -15
- package/dist/providers/index.js +0 -56
- package/dist/recorder/browser-recorder.d.ts +0 -22
- package/dist/recorder/browser-recorder.js +0 -205
- package/dist/rescan/diff-engine.d.ts +0 -5
- package/dist/rescan/diff-engine.js +0 -312
- package/dist/rescan/index.d.ts +0 -3
- package/dist/rescan/index.js +0 -2
- package/dist/rescan/rescan-runner.d.ts +0 -42
- package/dist/rescan/rescan-runner.js +0 -69
- package/dist/rescan/rescan-scheduler.d.ts +0 -41
- package/dist/rescan/rescan-scheduler.js +0 -179
- package/dist/site-transformer/browser-tools.d.ts +0 -10
- package/dist/site-transformer/browser-tools.js +0 -59
- package/dist/site-transformer/index.d.ts +0 -2
- package/dist/site-transformer/index.js +0 -2
- package/dist/site-transformer/selector-healer.d.ts +0 -8
- package/dist/site-transformer/selector-healer.js +0 -106
- package/dist/site-transformer/tool-generator.d.ts +0 -13
- package/dist/site-transformer/tool-generator.js +0 -245
- package/dist/transformer/auth-detector.d.ts +0 -13
- package/dist/transformer/auth-detector.js +0 -90
- package/dist/transformer/catalog-builder.d.ts +0 -18
- package/dist/transformer/catalog-builder.js +0 -56
- package/dist/transformer/client-compat.d.ts +0 -6
- package/dist/transformer/client-compat.js +0 -44
- package/dist/transformer/har-clusterer.d.ts +0 -9
- package/dist/transformer/har-clusterer.js +0 -27
- package/dist/transformer/har-dedup.d.ts +0 -10
- package/dist/transformer/har-dedup.js +0 -81
- package/dist/transformer/har-schema-inferrer.d.ts +0 -15
- package/dist/transformer/har-schema-inferrer.js +0 -90
- package/dist/transformer/har-to-operations.d.ts +0 -13
- package/dist/transformer/har-to-operations.js +0 -192
- package/dist/transformer/index.d.ts +0 -8
- package/dist/transformer/index.js +0 -6
- package/dist/transformer/llm-namer.d.ts +0 -6
- package/dist/transformer/llm-namer.js +0 -59
- package/dist/transformer/naming.d.ts +0 -4
- package/dist/transformer/naming.js +0 -30
- package/dist/transformer/operation-filter.d.ts +0 -13
- package/dist/transformer/operation-filter.js +0 -52
- package/dist/transformer/resource-builder.d.ts +0 -12
- package/dist/transformer/resource-builder.js +0 -80
- package/dist/transformer/schema-merger.d.ts +0 -14
- package/dist/transformer/schema-merger.js +0 -65
- package/dist/transformer/tool-builder.d.ts +0 -3
- package/dist/transformer/tool-builder.js +0 -114
- package/dist/types/index.d.ts +0 -131
- package/dist/types/index.js +0 -1
- package/dist/types/site.d.ts +0 -284
- package/dist/types/site.js +0 -8
- package/dist/utils/fail.d.ts +0 -48
- package/dist/utils/fail.js +0 -204
- package/dist/utils/fs.d.ts +0 -5
- package/dist/utils/fs.js +0 -28
- package/dist/utils/interactive.d.ts +0 -6
- package/dist/utils/interactive.js +0 -30
- package/dist/utils/logger.d.ts +0 -1
- package/dist/utils/logger.js +0 -2
- package/dist/utils/sanitize.d.ts +0 -28
- package/dist/utils/sanitize.js +0 -44
- package/dist/utils/watcher.d.ts +0 -11
- package/dist/utils/watcher.js +0 -36
|
@@ -1,123 +0,0 @@
|
|
|
1
|
-
<div class="admin-page">
|
|
2
|
-
<div class="admin-page-header">
|
|
3
|
-
<h1>System Overview</h1>
|
|
4
|
-
</div>
|
|
5
|
-
|
|
6
|
-
<div id="admin-stats" hx-get="/admin/_stats" hx-trigger="every 10s" hx-swap="innerHTML" aria-live="polite">
|
|
7
|
-
{{> admin-stats}}
|
|
8
|
-
</div>
|
|
9
|
-
|
|
10
|
-
<div class="health-panel">
|
|
11
|
-
<h2>Health</h2>
|
|
12
|
-
<div class="health-grid">
|
|
13
|
-
<div class="health-item">
|
|
14
|
-
<span class="health-badge {{#if health.db}}health-badge--ok{{else}}health-badge--bad{{/if}}">{{#if health.db}}OK{{else}}OFF{{/if}}</span>
|
|
15
|
-
<div class="health-meta">
|
|
16
|
-
<span class="health-name">Database</span>
|
|
17
|
-
<span class="health-sub">{{#if health.db}}reachable{{else}}in-memory mode{{/if}}</span>
|
|
18
|
-
</div>
|
|
19
|
-
</div>
|
|
20
|
-
<div class="health-item">
|
|
21
|
-
<span class="health-badge {{#if health.stripe}}health-badge--ok{{else}}health-badge--bad{{/if}}">{{#if health.stripe}}OK{{else}}OFF{{/if}}</span>
|
|
22
|
-
<div class="health-meta">
|
|
23
|
-
<span class="health-name">Stripe</span>
|
|
24
|
-
<span class="health-sub">{{#if health.stripe}}configured{{else}}not configured{{/if}}</span>
|
|
25
|
-
</div>
|
|
26
|
-
</div>
|
|
27
|
-
<div class="health-item">
|
|
28
|
-
<span class="health-badge health-badge--neutral">{{health.backend}}</span>
|
|
29
|
-
<div class="health-meta">
|
|
30
|
-
<span class="health-name">Container backend</span>
|
|
31
|
-
<span class="health-sub">driver</span>
|
|
32
|
-
</div>
|
|
33
|
-
</div>
|
|
34
|
-
<div class="health-item">
|
|
35
|
-
<span class="health-badge {{#if health.ramOk}}health-badge--ok{{else}}health-badge--bad{{/if}}">{{#if health.ramOk}}OK{{else}}ALERT{{/if}}</span>
|
|
36
|
-
<div class="health-meta">
|
|
37
|
-
<span class="health-name">RAM pressure</span>
|
|
38
|
-
<span class="health-sub">{{health.memUsedPct}}% used</span>
|
|
39
|
-
</div>
|
|
40
|
-
</div>
|
|
41
|
-
<div class="health-item">
|
|
42
|
-
<span class="health-badge {{#if health.diskOk}}health-badge--ok{{else}}health-badge--bad{{/if}}">{{#if health.diskOk}}OK{{else}}ALERT{{/if}}</span>
|
|
43
|
-
<div class="health-meta">
|
|
44
|
-
<span class="health-name">Disk pressure</span>
|
|
45
|
-
<span class="health-sub">{{health.diskUsedPct}}% used</span>
|
|
46
|
-
</div>
|
|
47
|
-
</div>
|
|
48
|
-
</div>
|
|
49
|
-
{{#if health.alerts.length}}
|
|
50
|
-
<ul class="health-alerts">
|
|
51
|
-
{{#each health.alerts}}<li>{{this}}</li>{{/each}}
|
|
52
|
-
</ul>
|
|
53
|
-
{{/if}}
|
|
54
|
-
</div>
|
|
55
|
-
|
|
56
|
-
<div class="chart-panel">
|
|
57
|
-
<div class="chart-panel-header">
|
|
58
|
-
<h2>API failure rate</h2>
|
|
59
|
-
<span class="chart-panel-meta">last 60 minutes</span>
|
|
60
|
-
</div>
|
|
61
|
-
<div class="failure-rate-grid">
|
|
62
|
-
<div class="stat-card">
|
|
63
|
-
<span class="stat-card-value">{{failure.requests}}</span>
|
|
64
|
-
<span class="stat-card-label">Requests (last hour)</span>
|
|
65
|
-
</div>
|
|
66
|
-
<div class="stat-card">
|
|
67
|
-
<span class="stat-card-value {{#if (eq failure.serverErrorRatePct '0.0')}}status-green{{else}}status-red{{/if}}">{{failure.serverErrorRatePct}}%</span>
|
|
68
|
-
<span class="stat-card-label">Server error rate (5xx)</span>
|
|
69
|
-
</div>
|
|
70
|
-
<div class="stat-card">
|
|
71
|
-
<span class="stat-card-value">{{failure.clientErrorRatePct}}%</span>
|
|
72
|
-
<span class="stat-card-label">Client error rate (4xx)</span>
|
|
73
|
-
</div>
|
|
74
|
-
</div>
|
|
75
|
-
<div class="chart-box">
|
|
76
|
-
<span class="chart-box-label">Requests / minute (live)</span>
|
|
77
|
-
{{{lastHourChart}}}
|
|
78
|
-
</div>
|
|
79
|
-
</div>
|
|
80
|
-
|
|
81
|
-
<div class="chart-panel">
|
|
82
|
-
<div class="chart-panel-header">
|
|
83
|
-
<h2>History</h2>
|
|
84
|
-
<span class="chart-panel-meta">last 24 hours</span>
|
|
85
|
-
</div>
|
|
86
|
-
{{#if hasHistory}}
|
|
87
|
-
<div class="chart-grid">
|
|
88
|
-
<div class="chart-box">
|
|
89
|
-
<span class="chart-box-label">Requests vs 5xx errors</span>
|
|
90
|
-
{{{charts.requestsErrors}}}
|
|
91
|
-
<div class="chart-legend">
|
|
92
|
-
<span class="chart-legend-item"><span class="chart-swatch chart-swatch--a"></span>Requests</span>
|
|
93
|
-
<span class="chart-legend-item"><span class="chart-swatch chart-swatch--b"></span>5xx errors</span>
|
|
94
|
-
</div>
|
|
95
|
-
</div>
|
|
96
|
-
<div class="chart-box">
|
|
97
|
-
<span class="chart-box-label">Memory vs disk used (%)</span>
|
|
98
|
-
{{{charts.memDisk}}}
|
|
99
|
-
<div class="chart-legend">
|
|
100
|
-
<span class="chart-legend-item"><span class="chart-swatch chart-swatch--a"></span>Memory</span>
|
|
101
|
-
<span class="chart-legend-item"><span class="chart-swatch chart-swatch--b"></span>Disk</span>
|
|
102
|
-
</div>
|
|
103
|
-
</div>
|
|
104
|
-
<div class="chart-box">
|
|
105
|
-
<span class="chart-box-label">Total users</span>
|
|
106
|
-
{{{charts.users}}}
|
|
107
|
-
</div>
|
|
108
|
-
<div class="chart-box">
|
|
109
|
-
<span class="chart-box-label">Total servers</span>
|
|
110
|
-
{{{charts.servers}}}
|
|
111
|
-
</div>
|
|
112
|
-
</div>
|
|
113
|
-
{{else}}
|
|
114
|
-
<div class="chart-empty">
|
|
115
|
-
{{#if historyEmpty}}
|
|
116
|
-
<p>History requires <code>DATABASE_URL</code>. Configure a database to retain metric samples across restarts.</p>
|
|
117
|
-
{{else}}
|
|
118
|
-
<p>No metric samples recorded yet. Charts will populate as the sampler runs.</p>
|
|
119
|
-
{{/if}}
|
|
120
|
-
</div>
|
|
121
|
-
{{/if}}
|
|
122
|
-
</div>
|
|
123
|
-
</div>
|
|
@@ -1,129 +0,0 @@
|
|
|
1
|
-
<div class="admin-page" x-data="adminServers()">
|
|
2
|
-
<div class="admin-page-header">
|
|
3
|
-
<h1>All Servers</h1>
|
|
4
|
-
<span class="admin-page-count">{{servers.length}} total</span>
|
|
5
|
-
</div>
|
|
6
|
-
|
|
7
|
-
<input
|
|
8
|
-
type="text"
|
|
9
|
-
class="search-input"
|
|
10
|
-
placeholder="Filter by slug, user, or status..."
|
|
11
|
-
x-model="search"
|
|
12
|
-
>
|
|
13
|
-
|
|
14
|
-
<div class="admin-table-wrap">
|
|
15
|
-
<table class="admin-table">
|
|
16
|
-
<thead>
|
|
17
|
-
<tr>
|
|
18
|
-
<th @click="sortBy('slug')" :class="sortClass('slug')">Slug</th>
|
|
19
|
-
<th @click="sortBy('status')" :class="sortClass('status')">Status</th>
|
|
20
|
-
<th @click="sortBy('userId')" :class="sortClass('userId')">User</th>
|
|
21
|
-
<th @click="sortBy('toolCount')" :class="sortClass('toolCount')">Tools</th>
|
|
22
|
-
<th @click="sortBy('port')" :class="sortClass('port')">Port</th>
|
|
23
|
-
<th @click="sortBy('createdAt')" :class="sortClass('createdAt')">Created</th>
|
|
24
|
-
<th @click="sortBy('lastActiveAt')" :class="sortClass('lastActiveAt')">Last Active</th>
|
|
25
|
-
<th>Actions</th>
|
|
26
|
-
</tr>
|
|
27
|
-
</thead>
|
|
28
|
-
<tbody>
|
|
29
|
-
<template x-for="server in filteredServers()" :key="server.slug">
|
|
30
|
-
<tr>
|
|
31
|
-
<td><code x-text="server.slug"></code></td>
|
|
32
|
-
<td>
|
|
33
|
-
<span
|
|
34
|
-
class="status-dot"
|
|
35
|
-
:class="{
|
|
36
|
-
'status-green': server.status === 'running',
|
|
37
|
-
'status-gray': server.status === 'stopped',
|
|
38
|
-
'status-red': server.status === 'error',
|
|
39
|
-
'status-yellow': server.status === 'building'
|
|
40
|
-
}"
|
|
41
|
-
x-text="server.status"
|
|
42
|
-
></span>
|
|
43
|
-
</td>
|
|
44
|
-
<td x-text="server.userEmail || server.userId || '(anonymous)'"></td>
|
|
45
|
-
<td x-text="server.toolCount"></td>
|
|
46
|
-
<td><code x-text="server.port"></code></td>
|
|
47
|
-
<td x-text="formatDate(server.createdAt)"></td>
|
|
48
|
-
<td x-text="formatDate(server.lastActiveAt)"></td>
|
|
49
|
-
<td class="admin-actions">
|
|
50
|
-
<form method="POST" :action="'/admin/servers/' + server.slug + '/delete'" style="display:inline">
|
|
51
|
-
<input type="hidden" name="_csrf" value="{{csrfToken}}">
|
|
52
|
-
<button
|
|
53
|
-
type="submit"
|
|
54
|
-
class="btn btn-sm btn-danger"
|
|
55
|
-
@click.prevent="confirmDelete($event, server.slug)"
|
|
56
|
-
>Delete</button>
|
|
57
|
-
</form>
|
|
58
|
-
</td>
|
|
59
|
-
</tr>
|
|
60
|
-
</template>
|
|
61
|
-
<template x-if="filteredServers().length === 0">
|
|
62
|
-
<tr>
|
|
63
|
-
<td colspan="8" class="admin-table-empty">No servers match your filter.</td>
|
|
64
|
-
</tr>
|
|
65
|
-
</template>
|
|
66
|
-
</tbody>
|
|
67
|
-
</table>
|
|
68
|
-
</div>
|
|
69
|
-
</div>
|
|
70
|
-
|
|
71
|
-
<script>
|
|
72
|
-
function adminServers() {
|
|
73
|
-
return {
|
|
74
|
-
search: '',
|
|
75
|
-
sortCol: 'createdAt',
|
|
76
|
-
sortDir: 'desc',
|
|
77
|
-
servers: {{{json servers}}},
|
|
78
|
-
|
|
79
|
-
sortBy(col) {
|
|
80
|
-
if (this.sortCol === col) {
|
|
81
|
-
this.sortDir = this.sortDir === 'asc' ? 'desc' : 'asc';
|
|
82
|
-
} else {
|
|
83
|
-
this.sortCol = col;
|
|
84
|
-
this.sortDir = 'asc';
|
|
85
|
-
}
|
|
86
|
-
},
|
|
87
|
-
|
|
88
|
-
sortClass(col) {
|
|
89
|
-
if (this.sortCol !== col) return 'sortable';
|
|
90
|
-
return 'sortable sorted-' + this.sortDir;
|
|
91
|
-
},
|
|
92
|
-
|
|
93
|
-
filteredServers() {
|
|
94
|
-
let result = this.servers;
|
|
95
|
-
const q = this.search.toLowerCase().trim();
|
|
96
|
-
if (q) {
|
|
97
|
-
result = result.filter(s =>
|
|
98
|
-
s.slug.toLowerCase().includes(q) ||
|
|
99
|
-
(s.userEmail || '').toLowerCase().includes(q) ||
|
|
100
|
-
(s.userId || '').toLowerCase().includes(q) ||
|
|
101
|
-
s.status.toLowerCase().includes(q)
|
|
102
|
-
);
|
|
103
|
-
}
|
|
104
|
-
const col = this.sortCol;
|
|
105
|
-
const dir = this.sortDir === 'asc' ? 1 : -1;
|
|
106
|
-
result = [...result].sort((a, b) => {
|
|
107
|
-
const va = a[col] ?? '';
|
|
108
|
-
const vb = b[col] ?? '';
|
|
109
|
-
if (typeof va === 'number' && typeof vb === 'number') return (va - vb) * dir;
|
|
110
|
-
return String(va).localeCompare(String(vb)) * dir;
|
|
111
|
-
});
|
|
112
|
-
return result;
|
|
113
|
-
},
|
|
114
|
-
|
|
115
|
-
formatDate(iso) {
|
|
116
|
-
if (!iso) return '';
|
|
117
|
-
const d = new Date(iso);
|
|
118
|
-
if (isNaN(d.getTime())) return iso;
|
|
119
|
-
return d.toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric' });
|
|
120
|
-
},
|
|
121
|
-
|
|
122
|
-
confirmDelete(event, slug) {
|
|
123
|
-
if (confirm('Delete server "' + slug + '"? This will stop the container and remove all data.')) {
|
|
124
|
-
event.target.closest('form').submit();
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
};
|
|
128
|
-
}
|
|
129
|
-
</script>
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
<div class="admin-page">
|
|
2
|
-
<div class="admin-page-header">
|
|
3
|
-
<h1>Telemetry</h1>
|
|
4
|
-
<span class="admin-page-count">{{groups.length}} groups</span>
|
|
5
|
-
</div>
|
|
6
|
-
|
|
7
|
-
<p class="form-hint">CLI crash and error reports, grouped by fingerprint. PII is stripped at ingest.</p>
|
|
8
|
-
|
|
9
|
-
<div class="admin-table-wrap">
|
|
10
|
-
<table class="admin-table">
|
|
11
|
-
<thead>
|
|
12
|
-
<tr>
|
|
13
|
-
<th>Count</th>
|
|
14
|
-
<th>Last seen</th>
|
|
15
|
-
<th>Command</th>
|
|
16
|
-
<th>Error</th>
|
|
17
|
-
<th>CLI</th>
|
|
18
|
-
<th>Platform</th>
|
|
19
|
-
</tr>
|
|
20
|
-
</thead>
|
|
21
|
-
<tbody>
|
|
22
|
-
{{#each groups}}
|
|
23
|
-
<tr>
|
|
24
|
-
<td><span class="telemetry-count">{{this.count}}</span></td>
|
|
25
|
-
<td>{{formatDate this.lastSeen}}</td>
|
|
26
|
-
<td><code>{{this.command}}</code></td>
|
|
27
|
-
<td class="telemetry-error" title="{{this.errorMessage}}">{{truncate this.errorMessage 120}}</td>
|
|
28
|
-
<td><code>{{this.cliVersion}}</code></td>
|
|
29
|
-
<td>{{this.platform}}</td>
|
|
30
|
-
</tr>
|
|
31
|
-
{{else}}
|
|
32
|
-
<tr>
|
|
33
|
-
<td colspan="6" class="admin-table-empty">No telemetry reports yet.</td>
|
|
34
|
-
</tr>
|
|
35
|
-
{{/each}}
|
|
36
|
-
</tbody>
|
|
37
|
-
</table>
|
|
38
|
-
</div>
|
|
39
|
-
</div>
|
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
<div class="admin-page">
|
|
2
|
-
<div class="admin-page-header">
|
|
3
|
-
<a href="/admin/users" class="admin-back-link">← Users</a>
|
|
4
|
-
<h1>{{targetUser.email}}</h1>
|
|
5
|
-
</div>
|
|
6
|
-
|
|
7
|
-
<div class="admin-stats">
|
|
8
|
-
<div class="stat-card">
|
|
9
|
-
<span class="stat-card-value">
|
|
10
|
-
<span class="plan-badge plan-badge--{{targetUser.plan}}">{{targetUser.plan}}</span>
|
|
11
|
-
</span>
|
|
12
|
-
<span class="stat-card-label">Plan</span>
|
|
13
|
-
</div>
|
|
14
|
-
<div class="stat-card">
|
|
15
|
-
<span class="stat-card-value">{{balance}}</span>
|
|
16
|
-
<span class="stat-card-label">Credit Balance</span>
|
|
17
|
-
</div>
|
|
18
|
-
<div class="stat-card">
|
|
19
|
-
<span class="stat-card-value">{{serverCount}}</span>
|
|
20
|
-
<span class="stat-card-label">Servers</span>
|
|
21
|
-
</div>
|
|
22
|
-
<div class="stat-card">
|
|
23
|
-
<span class="stat-card-value {{#if targetUser.isAdmin}}status-green{{/if}}">{{#if targetUser.isAdmin}}Yes{{else}}No{{/if}}</span>
|
|
24
|
-
<span class="stat-card-label">Admin</span>
|
|
25
|
-
</div>
|
|
26
|
-
</div>
|
|
27
|
-
|
|
28
|
-
<div class="system-info">
|
|
29
|
-
<h2>Account</h2>
|
|
30
|
-
<dl class="system-info-list">
|
|
31
|
-
<div class="system-info-row">
|
|
32
|
-
<dt>Email</dt>
|
|
33
|
-
<dd>{{targetUser.email}}</dd>
|
|
34
|
-
</div>
|
|
35
|
-
<div class="system-info-row">
|
|
36
|
-
<dt>Registered</dt>
|
|
37
|
-
<dd>{{formatDate targetUser.createdAt}}</dd>
|
|
38
|
-
</div>
|
|
39
|
-
<div class="system-info-row">
|
|
40
|
-
<dt>Last login</dt>
|
|
41
|
-
<dd>{{#if targetUser.lastLoginAt}}{{formatDate targetUser.lastLoginAt}}{{else}}—{{/if}}</dd>
|
|
42
|
-
</div>
|
|
43
|
-
</dl>
|
|
44
|
-
</div>
|
|
45
|
-
|
|
46
|
-
<div class="credit-panel">
|
|
47
|
-
<h2>Adjust credits</h2>
|
|
48
|
-
<p class="form-hint">Grant or revoke promotional tool-call credits. Recorded in the ledger below.</p>
|
|
49
|
-
<form method="POST" action="/admin/users/{{targetUser.id}}/credits" class="credit-form">
|
|
50
|
-
<input type="hidden" name="_csrf" value="{{csrfToken}}">
|
|
51
|
-
<div class="credit-form-row">
|
|
52
|
-
<label class="credit-form-field">
|
|
53
|
-
<span>Amount</span>
|
|
54
|
-
<input type="number" name="amount" min="1" max="100000000" step="1" required class="search-input" placeholder="e.g. 1000">
|
|
55
|
-
</label>
|
|
56
|
-
<div class="credit-form-actions">
|
|
57
|
-
<button type="submit" name="action" value="grant" class="btn btn-primary">Grant</button>
|
|
58
|
-
<button type="submit" name="action" value="revoke" class="btn btn-secondary">Revoke</button>
|
|
59
|
-
</div>
|
|
60
|
-
</div>
|
|
61
|
-
</form>
|
|
62
|
-
</div>
|
|
63
|
-
|
|
64
|
-
<div class="admin-table-wrap">
|
|
65
|
-
<h2 class="ledger-heading">Recent ledger</h2>
|
|
66
|
-
<table class="admin-table">
|
|
67
|
-
<thead>
|
|
68
|
-
<tr>
|
|
69
|
-
<th>When</th>
|
|
70
|
-
<th>Change</th>
|
|
71
|
-
<th>Reason</th>
|
|
72
|
-
<th>Balance after</th>
|
|
73
|
-
</tr>
|
|
74
|
-
</thead>
|
|
75
|
-
<tbody>
|
|
76
|
-
{{#each ledger}}
|
|
77
|
-
<tr>
|
|
78
|
-
<td>{{formatDate this.createdAt}}</td>
|
|
79
|
-
<td><span class="{{#if this.isCredit}}status-green{{else}}status-red{{/if}}">{{this.deltaLabel}}</span></td>
|
|
80
|
-
<td><code>{{this.reason}}</code></td>
|
|
81
|
-
<td>{{this.balanceAfter}}</td>
|
|
82
|
-
</tr>
|
|
83
|
-
{{else}}
|
|
84
|
-
<tr>
|
|
85
|
-
<td colspan="4" class="admin-table-empty">No credit activity yet.</td>
|
|
86
|
-
</tr>
|
|
87
|
-
{{/each}}
|
|
88
|
-
</tbody>
|
|
89
|
-
</table>
|
|
90
|
-
</div>
|
|
91
|
-
</div>
|
|
@@ -1,179 +0,0 @@
|
|
|
1
|
-
<div class="admin-page" x-data="adminUsers()">
|
|
2
|
-
<div class="admin-page-header">
|
|
3
|
-
<h1>User Management</h1>
|
|
4
|
-
<span class="admin-page-count">{{users.length}} total</span>
|
|
5
|
-
</div>
|
|
6
|
-
|
|
7
|
-
<input
|
|
8
|
-
type="text"
|
|
9
|
-
class="search-input"
|
|
10
|
-
placeholder="Filter by email or plan..."
|
|
11
|
-
x-model="search"
|
|
12
|
-
>
|
|
13
|
-
|
|
14
|
-
<div class="admin-table-wrap">
|
|
15
|
-
<table class="admin-table">
|
|
16
|
-
<thead>
|
|
17
|
-
<tr>
|
|
18
|
-
<th @click="sortBy('email')" :class="sortClass('email')">Email</th>
|
|
19
|
-
<th @click="sortBy('plan')" :class="sortClass('plan')">Plan</th>
|
|
20
|
-
<th @click="sortBy('isAdmin')" :class="sortClass('isAdmin')">Admin?</th>
|
|
21
|
-
<th @click="sortBy('serverCount')" :class="sortClass('serverCount')">Servers</th>
|
|
22
|
-
<th @click="sortBy('createdAt')" :class="sortClass('createdAt')">Registered</th>
|
|
23
|
-
<th @click="sortBy('lastLoginAt')" :class="sortClass('lastLoginAt')">Last Login</th>
|
|
24
|
-
<th>Actions</th>
|
|
25
|
-
</tr>
|
|
26
|
-
</thead>
|
|
27
|
-
<tbody>
|
|
28
|
-
<template x-for="user in filteredUsers()" :key="user.id">
|
|
29
|
-
<tr>
|
|
30
|
-
<td><a class="admin-row-link" :href="'/admin/users/' + user.id" x-text="user.email"></a></td>
|
|
31
|
-
<td>
|
|
32
|
-
<span
|
|
33
|
-
class="plan-badge"
|
|
34
|
-
:class="'plan-badge--' + user.plan"
|
|
35
|
-
x-text="user.plan"
|
|
36
|
-
></span>
|
|
37
|
-
</td>
|
|
38
|
-
<td>
|
|
39
|
-
<span
|
|
40
|
-
x-show="user.isAdmin"
|
|
41
|
-
class="admin-badge"
|
|
42
|
-
>admin</span>
|
|
43
|
-
</td>
|
|
44
|
-
<td x-text="user.serverCount"></td>
|
|
45
|
-
<td x-text="formatDate(user.createdAt)"></td>
|
|
46
|
-
<td x-text="formatDate(user.lastLoginAt)"></td>
|
|
47
|
-
<td class="admin-actions">
|
|
48
|
-
<form
|
|
49
|
-
class="inline-action"
|
|
50
|
-
method="POST"
|
|
51
|
-
:action="'/admin/users/' + user.id + '/plan'"
|
|
52
|
-
hx-post
|
|
53
|
-
:hx-post="'/admin/users/' + user.id + '/plan'"
|
|
54
|
-
hx-swap="none"
|
|
55
|
-
@htmx:after-request="handlePlanChange($event, user)"
|
|
56
|
-
>
|
|
57
|
-
<input type="hidden" name="_csrf" value="{{csrfToken}}">
|
|
58
|
-
<select name="plan" :value="user.plan" class="admin-select" @change="$el.closest('form').requestSubmit()">
|
|
59
|
-
<option value="free" :selected="user.plan === 'free'">free</option>
|
|
60
|
-
<option value="hobbyist" :selected="user.plan === 'hobbyist'">hobbyist</option>
|
|
61
|
-
<option value="pro" :selected="user.plan === 'pro'">pro</option>
|
|
62
|
-
<option value="team" :selected="user.plan === 'team'">team</option>
|
|
63
|
-
<option value="enterprise" :selected="user.plan === 'enterprise'">enterprise</option>
|
|
64
|
-
</select>
|
|
65
|
-
</form>
|
|
66
|
-
|
|
67
|
-
<form
|
|
68
|
-
class="inline-action"
|
|
69
|
-
method="POST"
|
|
70
|
-
:action="'/admin/users/' + user.id + '/admin'"
|
|
71
|
-
hx-post
|
|
72
|
-
:hx-post="'/admin/users/' + user.id + '/admin'"
|
|
73
|
-
hx-swap="none"
|
|
74
|
-
@htmx:after-request="handleAdminToggle($event, user)"
|
|
75
|
-
>
|
|
76
|
-
<input type="hidden" name="_csrf" value="{{csrfToken}}">
|
|
77
|
-
<button type="submit" class="btn btn-sm btn-secondary" x-text="user.isAdmin ? 'Revoke admin' : 'Make admin'"></button>
|
|
78
|
-
</form>
|
|
79
|
-
|
|
80
|
-
<form
|
|
81
|
-
class="inline-action"
|
|
82
|
-
method="POST"
|
|
83
|
-
:action="'/admin/users/' + user.id + '/delete'"
|
|
84
|
-
>
|
|
85
|
-
<input type="hidden" name="_csrf" value="{{csrfToken}}">
|
|
86
|
-
<button
|
|
87
|
-
type="submit"
|
|
88
|
-
class="btn btn-sm btn-danger"
|
|
89
|
-
@click.prevent="confirmDelete($event, user)"
|
|
90
|
-
>Delete</button>
|
|
91
|
-
</form>
|
|
92
|
-
</td>
|
|
93
|
-
</tr>
|
|
94
|
-
</template>
|
|
95
|
-
<template x-if="filteredUsers().length === 0">
|
|
96
|
-
<tr>
|
|
97
|
-
<td colspan="7" class="admin-table-empty">No users match your filter.</td>
|
|
98
|
-
</tr>
|
|
99
|
-
</template>
|
|
100
|
-
</tbody>
|
|
101
|
-
</table>
|
|
102
|
-
</div>
|
|
103
|
-
</div>
|
|
104
|
-
|
|
105
|
-
<script>
|
|
106
|
-
function adminUsers() {
|
|
107
|
-
return {
|
|
108
|
-
search: '',
|
|
109
|
-
sortCol: 'createdAt',
|
|
110
|
-
sortDir: 'desc',
|
|
111
|
-
users: {{{json users}}},
|
|
112
|
-
|
|
113
|
-
sortBy(col) {
|
|
114
|
-
if (this.sortCol === col) {
|
|
115
|
-
this.sortDir = this.sortDir === 'asc' ? 'desc' : 'asc';
|
|
116
|
-
} else {
|
|
117
|
-
this.sortCol = col;
|
|
118
|
-
this.sortDir = 'asc';
|
|
119
|
-
}
|
|
120
|
-
},
|
|
121
|
-
|
|
122
|
-
sortClass(col) {
|
|
123
|
-
if (this.sortCol !== col) return 'sortable';
|
|
124
|
-
return 'sortable sorted-' + this.sortDir;
|
|
125
|
-
},
|
|
126
|
-
|
|
127
|
-
filteredUsers() {
|
|
128
|
-
let result = this.users;
|
|
129
|
-
const q = this.search.toLowerCase().trim();
|
|
130
|
-
if (q) {
|
|
131
|
-
result = result.filter(u =>
|
|
132
|
-
u.email.toLowerCase().includes(q) ||
|
|
133
|
-
u.plan.toLowerCase().includes(q)
|
|
134
|
-
);
|
|
135
|
-
}
|
|
136
|
-
const col = this.sortCol;
|
|
137
|
-
const dir = this.sortDir === 'asc' ? 1 : -1;
|
|
138
|
-
result = [...result].sort((a, b) => {
|
|
139
|
-
const va = a[col] ?? '';
|
|
140
|
-
const vb = b[col] ?? '';
|
|
141
|
-
if (typeof va === 'number' && typeof vb === 'number') return (va - vb) * dir;
|
|
142
|
-
if (typeof va === 'boolean' && typeof vb === 'boolean') return ((va ? 1 : 0) - (vb ? 1 : 0)) * dir;
|
|
143
|
-
return String(va).localeCompare(String(vb)) * dir;
|
|
144
|
-
});
|
|
145
|
-
return result;
|
|
146
|
-
},
|
|
147
|
-
|
|
148
|
-
formatDate(iso) {
|
|
149
|
-
if (!iso) return '';
|
|
150
|
-
const d = new Date(iso);
|
|
151
|
-
if (isNaN(d.getTime())) return iso;
|
|
152
|
-
return d.toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric' });
|
|
153
|
-
},
|
|
154
|
-
|
|
155
|
-
handlePlanChange(event, user) {
|
|
156
|
-
if (event.detail.successful) {
|
|
157
|
-
const form = event.target;
|
|
158
|
-
const select = form.querySelector('select[name="plan"]');
|
|
159
|
-
user.plan = select.value;
|
|
160
|
-
}
|
|
161
|
-
},
|
|
162
|
-
|
|
163
|
-
handleAdminToggle(event, user) {
|
|
164
|
-
if (event.detail.successful) {
|
|
165
|
-
user.isAdmin = !user.isAdmin;
|
|
166
|
-
}
|
|
167
|
-
},
|
|
168
|
-
|
|
169
|
-
confirmDelete(event, user) {
|
|
170
|
-
if (user.isAdmin) {
|
|
171
|
-
if (!confirm('This user is an admin. Are you sure you want to delete "' + user.email + '"?')) return;
|
|
172
|
-
} else {
|
|
173
|
-
if (!confirm('Delete user "' + user.email + '"? This cannot be undone.')) return;
|
|
174
|
-
}
|
|
175
|
-
event.target.closest('form').submit();
|
|
176
|
-
}
|
|
177
|
-
};
|
|
178
|
-
}
|
|
179
|
-
</script>
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
<h1>Reset password</h1>
|
|
2
|
-
<p class="auth-subtitle">Enter your email to receive a reset link</p>
|
|
3
|
-
|
|
4
|
-
{{#if error}}
|
|
5
|
-
<div class="auth-error" role="alert" aria-live="assertive">{{error}}</div>
|
|
6
|
-
{{/if}}
|
|
7
|
-
|
|
8
|
-
{{#if success}}
|
|
9
|
-
<div class="auth-success" role="status" aria-live="polite">{{success}}</div>
|
|
10
|
-
{{else}}
|
|
11
|
-
<form method="POST" action="/forgot-password">
|
|
12
|
-
<input type="hidden" name="_csrf" value="{{csrfToken}}">
|
|
13
|
-
|
|
14
|
-
<div class="form-group">
|
|
15
|
-
<label for="email">Email</label>
|
|
16
|
-
<input type="email" id="email" name="email" value="{{email}}" required autocomplete="email" autofocus>
|
|
17
|
-
</div>
|
|
18
|
-
|
|
19
|
-
<button type="submit" class="auth-submit">Send reset link</button>
|
|
20
|
-
</form>
|
|
21
|
-
{{/if}}
|
|
22
|
-
|
|
23
|
-
<div class="auth-footer">
|
|
24
|
-
<a href="/login">Back to sign in</a>
|
|
25
|
-
</div>
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
<h1>Sign in</h1>
|
|
2
|
-
<p class="auth-subtitle">Welcome back to mcpmake</p>
|
|
3
|
-
|
|
4
|
-
{{#if success}}
|
|
5
|
-
<div class="auth-success" role="status" aria-live="polite">{{success}}</div>
|
|
6
|
-
{{/if}}
|
|
7
|
-
|
|
8
|
-
{{#if error}}
|
|
9
|
-
<div class="auth-error" role="alert" aria-live="assertive">{{error}}</div>
|
|
10
|
-
{{/if}}
|
|
11
|
-
|
|
12
|
-
<form method="POST" action="/login">
|
|
13
|
-
<input type="hidden" name="_csrf" value="{{csrfToken}}">
|
|
14
|
-
|
|
15
|
-
<div class="form-group">
|
|
16
|
-
<label for="email">Email</label>
|
|
17
|
-
<input type="email" id="email" name="email" value="{{email}}" required autocomplete="email" autofocus>
|
|
18
|
-
</div>
|
|
19
|
-
|
|
20
|
-
<div class="form-group">
|
|
21
|
-
<label for="password">Password</label>
|
|
22
|
-
<input type="password" id="password" name="password" required autocomplete="current-password">
|
|
23
|
-
</div>
|
|
24
|
-
|
|
25
|
-
<button type="submit" class="auth-submit">Sign in</button>
|
|
26
|
-
</form>
|
|
27
|
-
|
|
28
|
-
<div class="auth-footer">
|
|
29
|
-
<a href="/forgot-password">Forgot your password?</a>
|
|
30
|
-
</div>
|
|
31
|
-
<div class="auth-footer">
|
|
32
|
-
Don't have an account? <a href="/register">Register</a>
|
|
33
|
-
</div>
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
<h1>Create account</h1>
|
|
2
|
-
<p class="auth-subtitle">Get started with mcpmake Cloud</p>
|
|
3
|
-
|
|
4
|
-
{{#if error}}
|
|
5
|
-
<div class="auth-error" role="alert" aria-live="assertive">{{error}}</div>
|
|
6
|
-
{{/if}}
|
|
7
|
-
|
|
8
|
-
<form method="POST" action="/register">
|
|
9
|
-
<input type="hidden" name="_csrf" value="{{csrfToken}}">
|
|
10
|
-
|
|
11
|
-
<div class="form-group">
|
|
12
|
-
<label for="email">Email</label>
|
|
13
|
-
<input type="email" id="email" name="email" value="{{email}}" required autocomplete="email" autofocus>
|
|
14
|
-
</div>
|
|
15
|
-
|
|
16
|
-
<div class="form-group">
|
|
17
|
-
<label for="password">Password</label>
|
|
18
|
-
<input type="password" id="password" name="password" required autocomplete="new-password" minlength="8">
|
|
19
|
-
<p class="form-hint">Minimum 8 characters</p>
|
|
20
|
-
</div>
|
|
21
|
-
|
|
22
|
-
<div class="form-group">
|
|
23
|
-
<label for="confirmPassword">Confirm password</label>
|
|
24
|
-
<input type="password" id="confirmPassword" name="confirmPassword" required autocomplete="new-password">
|
|
25
|
-
</div>
|
|
26
|
-
|
|
27
|
-
<button type="submit" class="auth-submit">Create account</button>
|
|
28
|
-
</form>
|
|
29
|
-
|
|
30
|
-
<div class="auth-footer">
|
|
31
|
-
Already have an account? <a href="/login">Sign in</a>
|
|
32
|
-
</div>
|