mirror of
https://github.com/paperclipai/paperclip
synced 2026-04-25 17:25:15 +02:00
Introduce bind presets for deployment setup
Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
@@ -4,6 +4,7 @@ import { existsSync, mkdirSync, readdirSync, rmSync, statSync, writeFileSync } f
|
||||
import path from "node:path";
|
||||
import { createInterface } from "node:readline/promises";
|
||||
import { stdin, stdout } from "node:process";
|
||||
import { BIND_MODES, type BindMode } from "@paperclipai/shared";
|
||||
import { createCapturedOutputBuffer, parseJsonResponseWithLimit } from "./dev-runner-output.mjs";
|
||||
import { shouldTrackDevServerPath } from "./dev-runner-paths.mjs";
|
||||
import { createDevServiceIdentity, repoRoot } from "./dev-service-profile.ts";
|
||||
@@ -62,13 +63,36 @@ const tailscaleAuthFlagNames = new Set([
|
||||
]);
|
||||
|
||||
let tailscaleAuth = false;
|
||||
let bindMode: BindMode | null = null;
|
||||
let bindHost: string | null = null;
|
||||
const forwardedArgs: string[] = [];
|
||||
|
||||
for (const arg of cliArgs) {
|
||||
for (let index = 0; index < cliArgs.length; index += 1) {
|
||||
const arg = cliArgs[index];
|
||||
if (tailscaleAuthFlagNames.has(arg)) {
|
||||
tailscaleAuth = true;
|
||||
continue;
|
||||
}
|
||||
if (arg === "--bind") {
|
||||
const value = cliArgs[index + 1];
|
||||
if (!value || value.startsWith("--") || !BIND_MODES.includes(value as BindMode)) {
|
||||
console.error(`[paperclip] invalid --bind value. Use one of: ${BIND_MODES.join(", ")}`);
|
||||
process.exit(1);
|
||||
}
|
||||
bindMode = value as BindMode;
|
||||
index += 1;
|
||||
continue;
|
||||
}
|
||||
if (arg === "--bind-host") {
|
||||
const value = cliArgs[index + 1];
|
||||
if (!value || value.startsWith("--")) {
|
||||
console.error("[paperclip] --bind-host requires a value");
|
||||
process.exit(1);
|
||||
}
|
||||
bindHost = value;
|
||||
index += 1;
|
||||
continue;
|
||||
}
|
||||
forwardedArgs.push(arg);
|
||||
}
|
||||
|
||||
@@ -78,6 +102,16 @@ if (process.env.npm_config_tailscale_auth === "true") {
|
||||
if (process.env.npm_config_authenticated_private === "true") {
|
||||
tailscaleAuth = true;
|
||||
}
|
||||
if (!bindMode && process.env.npm_config_bind && BIND_MODES.includes(process.env.npm_config_bind as BindMode)) {
|
||||
bindMode = process.env.npm_config_bind as BindMode;
|
||||
}
|
||||
if (!bindHost && process.env.npm_config_bind_host) {
|
||||
bindHost = process.env.npm_config_bind_host;
|
||||
}
|
||||
if (bindMode === "custom" && !bindHost) {
|
||||
console.error("[paperclip] --bind custom requires --bind-host <host>");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const env: NodeJS.ProcessEnv = {
|
||||
...process.env,
|
||||
@@ -94,13 +128,36 @@ if (mode === "watch") {
|
||||
env.PAPERCLIP_MIGRATION_AUTO_APPLY ??= "true";
|
||||
}
|
||||
|
||||
if (tailscaleAuth) {
|
||||
env.PAPERCLIP_DEPLOYMENT_MODE = "authenticated";
|
||||
env.PAPERCLIP_DEPLOYMENT_EXPOSURE = "private";
|
||||
env.PAPERCLIP_AUTH_BASE_URL_MODE = "auto";
|
||||
env.HOST = "0.0.0.0";
|
||||
console.log("[paperclip] dev mode: authenticated/private (tailscale-friendly) on 0.0.0.0");
|
||||
if (tailscaleAuth || bindMode) {
|
||||
const effectiveBind = bindMode ?? "lan";
|
||||
if (tailscaleAuth) {
|
||||
console.log("[paperclip] note: --tailscale-auth/--authenticated-private are legacy aliases for --bind lan");
|
||||
}
|
||||
env.PAPERCLIP_BIND = effectiveBind;
|
||||
if (bindHost) {
|
||||
env.PAPERCLIP_BIND_HOST = bindHost;
|
||||
} else {
|
||||
delete env.PAPERCLIP_BIND_HOST;
|
||||
}
|
||||
if (effectiveBind === "loopback" && !tailscaleAuth) {
|
||||
delete env.PAPERCLIP_DEPLOYMENT_MODE;
|
||||
delete env.PAPERCLIP_DEPLOYMENT_EXPOSURE;
|
||||
delete env.PAPERCLIP_AUTH_BASE_URL_MODE;
|
||||
console.log("[paperclip] dev mode: local_trusted (bind=loopback)");
|
||||
} else {
|
||||
env.PAPERCLIP_DEPLOYMENT_MODE = "authenticated";
|
||||
env.PAPERCLIP_DEPLOYMENT_EXPOSURE = "private";
|
||||
env.PAPERCLIP_AUTH_BASE_URL_MODE = "auto";
|
||||
console.log(
|
||||
`[paperclip] dev mode: authenticated/private (bind=${effectiveBind}${bindHost ? `:${bindHost}` : ""})`,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
delete env.PAPERCLIP_BIND;
|
||||
delete env.PAPERCLIP_BIND_HOST;
|
||||
delete env.PAPERCLIP_DEPLOYMENT_MODE;
|
||||
delete env.PAPERCLIP_DEPLOYMENT_EXPOSURE;
|
||||
delete env.PAPERCLIP_AUTH_BASE_URL_MODE;
|
||||
console.log("[paperclip] dev mode: local_trusted (default)");
|
||||
}
|
||||
|
||||
@@ -108,7 +165,7 @@ const serverPort = Number.parseInt(env.PORT ?? process.env.PORT ?? "3100", 10) |
|
||||
const devService = createDevServiceIdentity({
|
||||
mode,
|
||||
forwardedArgs,
|
||||
tailscaleAuth,
|
||||
networkProfile: tailscaleAuth ? `legacy:${bindMode ?? "lan"}` : (bindMode ?? "default"),
|
||||
port: serverPort,
|
||||
});
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ export const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)
|
||||
export function createDevServiceIdentity(input: {
|
||||
mode: "watch" | "dev";
|
||||
forwardedArgs: string[];
|
||||
tailscaleAuth: boolean;
|
||||
networkProfile: string;
|
||||
port: number;
|
||||
}) {
|
||||
const envFingerprint = createHash("sha256")
|
||||
@@ -16,7 +16,7 @@ export function createDevServiceIdentity(input: {
|
||||
JSON.stringify({
|
||||
mode: input.mode,
|
||||
forwardedArgs: input.forwardedArgs,
|
||||
tailscaleAuth: input.tailscaleAuth,
|
||||
networkProfile: input.networkProfile,
|
||||
port: input.port,
|
||||
}),
|
||||
)
|
||||
|
||||
@@ -237,6 +237,8 @@ async function main() {
|
||||
server: {
|
||||
deploymentMode: sourceConfig?.server?.deploymentMode ?? "local_trusted",
|
||||
exposure: sourceConfig?.server?.exposure ?? "private",
|
||||
...(sourceConfig?.server?.bind ? { bind: sourceConfig.server.bind } : {}),
|
||||
...(sourceConfig?.server?.customBindHost ? { customBindHost: sourceConfig.server.customBindHost } : {}),
|
||||
host: sourceConfig?.server?.host ?? "127.0.0.1",
|
||||
port: serverPort,
|
||||
allowedHostnames: sourceConfig?.server?.allowedHostnames ?? [],
|
||||
|
||||
Reference in New Issue
Block a user