diff --git a/src/__tests__/config.test.ts b/src/__tests__/config.test.ts index bced236..9466962 100644 --- a/src/__tests__/config.test.ts +++ b/src/__tests__/config.test.ts @@ -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"); + }); }); diff --git a/src/__tests__/index.test.ts b/src/__tests__/index.test.ts new file mode 100644 index 0000000..a6c9cc2 --- /dev/null +++ b/src/__tests__/index.test.ts @@ -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", + ]); + }); +}); diff --git a/src/config.ts b/src/config.ts index e2fd218..c1c1a06 100644 --- a/src/config.ts +++ b/src/config.ts @@ -7,6 +7,7 @@ export interface TunnelConfig { deviceSecret: string; port: number; previewPath?: string; + telegramMiniAppUrl?: string; } const PRIMARY_CONFIG_FILE = "spawndock.dev-tunnel.json"; @@ -49,8 +50,10 @@ function normalizeConfig(data: unknown): Partial { : 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 { @@ -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 }; } diff --git a/src/index.ts b/src/index.ts index 94f2fed..c482810 100644 --- a/src/index.ts +++ b/src/index.ts @@ -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(); }