@mybase-dev/cli 1.0.5 → 1.0.6
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/mybase.js +63 -1
- package/package.json +1 -1
package/dist/mybase.js
CHANGED
|
@@ -139,7 +139,7 @@ function parseDotenv(text) {
|
|
|
139
139
|
// package.json
|
|
140
140
|
var package_default = {
|
|
141
141
|
name: "@mybase-dev/cli",
|
|
142
|
-
version: "1.0.
|
|
142
|
+
version: "1.0.6",
|
|
143
143
|
description: "The mybase CLI: projects, keys, cron, queues, cache, rate limits, analytics, docs, and agent setup for a self-hosted mybase.",
|
|
144
144
|
type: "module",
|
|
145
145
|
repository: {
|
|
@@ -3759,6 +3759,7 @@ var compose_default = `# Runs mybase: the control plane (API + dashboard), the s
|
|
|
3759
3759
|
# MYBASE_S3_PUBLIC_URL=https://s3.<domain>
|
|
3760
3760
|
# MYBASE_TRUST_PROXY=cloudflare
|
|
3761
3761
|
# Optionally POSTGRES_BIND=127.0.0.1, GARAGE_S3_BIND=127.0.0.1, and VALKEY_BIND=127.0.0.1 to stop exposing those ports on the LAN.
|
|
3762
|
+
# Optionally CLOUDFLARED_REGION=us if the tunnel lands on far-away data centers (see \`mybase server status\`).
|
|
3762
3763
|
# 5. docker compose up -d
|
|
3763
3764
|
# Apps on serverless hosts reach Postgres at wss://mybase.<domain>/db with @neondatabase/serverless,
|
|
3764
3765
|
# or, with a router port forward, at a normal postgres:// URL (public Postgres, below).
|
|
@@ -3922,6 +3923,11 @@ services:
|
|
|
3922
3923
|
command: tunnel --no-autoupdate run
|
|
3923
3924
|
environment:
|
|
3924
3925
|
TUNNEL_TOKEN: \${CLOUDFLARE_TUNNEL_TOKEN:-}
|
|
3926
|
+
# Which Cloudflare data centers the tunnel connects to: empty = nearest by anycast, \`us\` = US only
|
|
3927
|
+
# (if \`mybase server status\` shows far-away colos, every request takes the detour).
|
|
3928
|
+
TUNNEL_REGION: \${CLOUDFLARED_REGION:-}
|
|
3929
|
+
# auto (QUIC, falls back to HTTP/2), quic, or http2 (if your network blocks or throttles UDP).
|
|
3930
|
+
TUNNEL_TRANSPORT_PROTOCOL: \${CLOUDFLARED_PROTOCOL:-auto}
|
|
3925
3931
|
depends_on:
|
|
3926
3932
|
- mybase
|
|
3927
3933
|
|
|
@@ -4253,6 +4259,25 @@ async function enableDockerOnBoot() {
|
|
|
4253
4259
|
return false;
|
|
4254
4260
|
}
|
|
4255
4261
|
}
|
|
4262
|
+
function tunnelConnections(logs) {
|
|
4263
|
+
const conns = new Map;
|
|
4264
|
+
for (const line of logs.split(`
|
|
4265
|
+
`)) {
|
|
4266
|
+
if (/Starting tunnel/.test(line))
|
|
4267
|
+
conns.clear();
|
|
4268
|
+
const index = Number(/connIndex=(\d+)/.exec(line)?.[1]);
|
|
4269
|
+
if (Number.isNaN(index))
|
|
4270
|
+
continue;
|
|
4271
|
+
if (/Registered tunnel connection/.test(line)) {
|
|
4272
|
+
const location = /location=(\S+)/.exec(line)?.[1];
|
|
4273
|
+
if (location)
|
|
4274
|
+
conns.set(index, { index, location, protocol: /protocol=(\S+)/.exec(line)?.[1] ?? null });
|
|
4275
|
+
} else if (/Unregistered tunnel connection|Connection terminated|Retrying connection|Serve tunnel error/.test(line)) {
|
|
4276
|
+
conns.delete(index);
|
|
4277
|
+
}
|
|
4278
|
+
}
|
|
4279
|
+
return [...conns.values()].sort((a, b) => a.index - b.index);
|
|
4280
|
+
}
|
|
4256
4281
|
|
|
4257
4282
|
// src/server-setup.ts
|
|
4258
4283
|
import { chmod as chmod2, mkdir as mkdir3 } from "fs/promises";
|
|
@@ -5044,6 +5069,7 @@ var serverUsage = ` server setup [--dir <dir>] Install mybase on this machi
|
|
|
5044
5069
|
[--admin-user <u> --admin-password-stdin] Without a terminal: defaults plus these flags
|
|
5045
5070
|
server status [--dir <dir>] Containers, health, and whether mybase starts on boot
|
|
5046
5071
|
server update [--dir <dir>] Download new images and restart (also refreshes compose.yml)
|
|
5072
|
+
server restart [--dir <dir>] Restart every container (API, Postgres, storage, cache, search, tunnel)
|
|
5047
5073
|
server tunnel [--dir <dir>] Add or replace the Cloudflare Tunnel [--tunnel-token <t> --domain <d>] | --off
|
|
5048
5074
|
server database-public [--dir <dir>] A normal postgres:// URL from anywhere: router port forward +
|
|
5049
5075
|
Let's Encrypt TLS + DNS kept on your IP (Cloudflare)
|
|
@@ -5076,6 +5102,10 @@ async function status(args) {
|
|
|
5076
5102
|
const health = await fetch(`${url}/health`, { signal: AbortSignal.timeout(3000) }).then(async (r) => r.ok ? (await r.json()).version ?? "unknown" : null).catch(() => null);
|
|
5077
5103
|
const autostart = values.MYBASE_RESTART !== "no";
|
|
5078
5104
|
const docker = dockerOnBoot();
|
|
5105
|
+
const tunnelOn = !!values.CLOUDFLARE_TUNNEL_TOKEN && containers.some((c) => c.Service === "cloudflared");
|
|
5106
|
+
const tunnelLogs = tunnelOn ? await compose(dir, ["logs", "--no-log-prefix", "--tail", "500", "cloudflared"]) : null;
|
|
5107
|
+
const tunnel = tunnelLogs?.ok ? tunnelConnections(`${tunnelLogs.stdout}
|
|
5108
|
+
${tunnelLogs.stderr}`) : null;
|
|
5079
5109
|
const data = {
|
|
5080
5110
|
dir,
|
|
5081
5111
|
url,
|
|
@@ -5084,6 +5114,7 @@ async function status(args) {
|
|
|
5084
5114
|
autostart: autostart && docker !== "disabled",
|
|
5085
5115
|
dockerOnBoot: docker,
|
|
5086
5116
|
publicUrl: values.CLOUDFLARE_TUNNEL_TOKEN ? values.MYBASE_PUBLIC_URL ?? null : null,
|
|
5117
|
+
tunnel,
|
|
5087
5118
|
containers: containers.map((c) => ({ service: c.Service, state: c.State, health: c.Health || null }))
|
|
5088
5119
|
};
|
|
5089
5120
|
print(data, () => {
|
|
@@ -5091,6 +5122,10 @@ async function status(args) {
|
|
|
5091
5122
|
console.log(` ${health ? green("\u25CF") : red("\u25CF")} ${url} ${health ? `version ${health}` : "not answering"}`);
|
|
5092
5123
|
if (data.publicUrl)
|
|
5093
5124
|
console.log(` ${dim2("public")} ${data.publicUrl}`);
|
|
5125
|
+
if (tunnel) {
|
|
5126
|
+
const where = tunnel.map((c) => `${c.location}${c.protocol ? ` ${c.protocol}` : ""}`).join(", ");
|
|
5127
|
+
console.log(` ${tunnel.length > 0 ? green("\u25CF") : red("\u25CF")} ${dim2("tunnel")} ${tunnel.length > 0 ? `${tunnel.length} connection(s): ${where}` : "not connected to Cloudflare (public URL answers 530)"}`);
|
|
5128
|
+
}
|
|
5094
5129
|
console.log(` ${dim2("starts on boot")} ${!autostart ? "no (mybase server autostart on)" : docker === "disabled" ? "no: Docker doesn't start at boot (sudo systemctl enable docker)" : "yes"}`);
|
|
5095
5130
|
console.log("");
|
|
5096
5131
|
if (containers.length === 0)
|
|
@@ -5121,6 +5156,31 @@ async function update(args) {
|
|
|
5121
5156
|
return print({ dir, version, composeUpdated: replaced }, () => {});
|
|
5122
5157
|
outro(`mybase ${version} is running at ${localUrl(values)}`);
|
|
5123
5158
|
}
|
|
5159
|
+
async function restart(args) {
|
|
5160
|
+
const dir = await serverDir(args);
|
|
5161
|
+
const { values } = await loadEnv(dir);
|
|
5162
|
+
if (!await stackExists(dir))
|
|
5163
|
+
throw new CliError("no containers to restart. Start them: mybase server update", 4);
|
|
5164
|
+
const s = ui.spinner();
|
|
5165
|
+
s.start("Restarting containers");
|
|
5166
|
+
const res = await compose(dir, ["restart"]);
|
|
5167
|
+
if (!res.ok) {
|
|
5168
|
+
s.stop("Restart failed");
|
|
5169
|
+
throw new CliError(`docker compose restart failed:
|
|
5170
|
+
${res.stderr}`);
|
|
5171
|
+
}
|
|
5172
|
+
s.message("Waiting for mybase to answer");
|
|
5173
|
+
const version = await waitHealthy(localUrl(values), 120000);
|
|
5174
|
+
s.stop(version ? "Restarted" : "Containers restarted");
|
|
5175
|
+
if (!version) {
|
|
5176
|
+
ui.warn("mybase didn't answer yet; check `mybase server status`.");
|
|
5177
|
+
process.exitCode = 1;
|
|
5178
|
+
}
|
|
5179
|
+
print({ dir, healthy: version !== null, version }, () => {
|
|
5180
|
+
if (version)
|
|
5181
|
+
console.log(`mybase ${version} is running at ${localUrl(values)}`);
|
|
5182
|
+
});
|
|
5183
|
+
}
|
|
5124
5184
|
async function tunnel(args) {
|
|
5125
5185
|
const dir = await serverDir(args);
|
|
5126
5186
|
const { text, values } = await loadEnv(dir);
|
|
@@ -5277,6 +5337,8 @@ async function server(command, args) {
|
|
|
5277
5337
|
await status(args);
|
|
5278
5338
|
else if (command === "update")
|
|
5279
5339
|
await update(args);
|
|
5340
|
+
else if (command === "restart")
|
|
5341
|
+
await restart(args);
|
|
5280
5342
|
else if (command === "tunnel")
|
|
5281
5343
|
await tunnel(args);
|
|
5282
5344
|
else if (command === "database-public")
|
package/package.json
CHANGED