Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions src/__tests__/config.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,21 @@ describe("resolveConfig", () => {
const config = resolveConfig([], dir);
expect(config.previewPath).toBe("/preview/my-app");
});

it("reads telegramMiniAppUrl from legacy spawndock.config.json", () => {
const dir = mkdtempSync(join(tmpdir(), "spawndock-config-"));
writeFileSync(
join(dir, "spawndock.config.json"),
JSON.stringify({
controlPlaneUrl: "http://localhost:8787",
projectSlug: "my-app",
deviceSecret: "secret123",
localPort: 4010,
telegramMiniAppUrl: "https://t.me/TMASpawnerBot/tma?startapp=my-app",
}),
);

const config = resolveConfig([], dir);
expect(config.telegramMiniAppUrl).toBe("https://t.me/TMASpawnerBot/tma?startapp=my-app");
});
});
28 changes: 28 additions & 0 deletions src/__tests__/index.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { describe, expect, it } from "vitest";
import { buildStartupMessages } from "../index.js";

describe("buildStartupMessages", () => {
it("prints the tunnel target and Telegram link when available", () => {
expect(buildStartupMessages({
controlPlane: "https://spawn-dock.w3voice.net",
projectSlug: "demo-app",
deviceSecret: "secret_123",
port: 3001,
telegramMiniAppUrl: "https://t.me/TMASpawnerBot/tma?startapp=demo-app",
})).toEqual([
"SpawnDock dev tunnel: demo-app -> http://127.0.0.1:3001",
"TMA URL: https://t.me/TMASpawnerBot/tma?startapp=demo-app",
]);
});

it("omits the Telegram link when the config does not include one", () => {
expect(buildStartupMessages({
controlPlane: "https://spawn-dock.w3voice.net",
projectSlug: "demo-app",
deviceSecret: "secret_123",
port: 3001,
})).toEqual([
"SpawnDock dev tunnel: demo-app -> http://127.0.0.1:3001",
]);
});
});
8 changes: 6 additions & 2 deletions src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export interface TunnelConfig {
deviceSecret: string;
port: number;
previewPath?: string;
telegramMiniAppUrl?: string;
}

const PRIMARY_CONFIG_FILE = "spawndock.dev-tunnel.json";
Expand Down Expand Up @@ -49,8 +50,10 @@ function normalizeConfig(data: unknown): Partial<TunnelConfig> {
: undefined;
const previewPath =
typeof record.previewPath === "string" ? record.previewPath : undefined;
const telegramMiniAppUrl =
typeof record.telegramMiniAppUrl === "string" ? record.telegramMiniAppUrl : undefined;

return { controlPlane, projectSlug, deviceSecret, port, previewPath };
return { controlPlane, projectSlug, deviceSecret, port, previewPath, telegramMiniAppUrl };
}

function readConfigFile(dir: string): Partial<TunnelConfig> {
Expand Down Expand Up @@ -145,10 +148,11 @@ export function resolveConfig(
const deviceSecret = args.deviceSecret ?? env.deviceSecret ?? file.deviceSecret;
const port = args.port ?? env.port ?? file.port ?? 3000;
const previewPath = file.previewPath;
const telegramMiniAppUrl = file.telegramMiniAppUrl;

if (!controlPlane) throw new Error("Missing --control-plane or SPAWNDOCK_CONTROL_PLANE");
if (!projectSlug) throw new Error("Missing --project-slug or SPAWNDOCK_PROJECT_SLUG");
if (!deviceSecret) throw new Error("Missing --device-secret or SPAWNDOCK_DEVICE_SECRET");

return { controlPlane, projectSlug, deviceSecret, port, previewPath };
return { controlPlane, projectSlug, deviceSecret, port, previewPath, telegramMiniAppUrl };
}
41 changes: 32 additions & 9 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,37 @@
#!/usr/bin/env node
import { resolveConfig } from "./config.js";
import { pathToFileURL } from "node:url";
import { resolveConfig, type TunnelConfig } from "./config.js";
import { createTunnel } from "./tunnel.js";

try {
const config = resolveConfig();
console.log(
export function buildStartupMessages(config: TunnelConfig): string[] {
const lines = [
`SpawnDock dev tunnel: ${config.projectSlug} -> http://127.0.0.1:${config.port}`,
);
createTunnel(config);
} catch (err: any) {
console.error(`Error: ${err.message}`);
process.exit(1);
];

if (typeof config.telegramMiniAppUrl === "string" && config.telegramMiniAppUrl.length > 0) {
lines.push(`TMA URL: ${config.telegramMiniAppUrl}`);
}

return lines;
}

export function runCli(): void {
try {
const config = resolveConfig();
for (const line of buildStartupMessages(config)) {
console.log(line);
}
createTunnel(config);
} catch (err: any) {
console.error(`Error: ${err.message}`);
process.exit(1);
}
}

const currentEntrypoint = process.argv[1]
? pathToFileURL(process.argv[1]).href
: "";

if (currentEntrypoint === import.meta.url) {
runCli();
}