UNPKG

4bnode

Version:

4bnode is a CLI-powered backend development platform with a built-in visual dashboard to generate, manage, and test Node.js/Express APIs faster.

90 lines (77 loc) 3.18 kB
#!/usr/bin/env node import fs from "fs"; import path from "path"; import { input } from "@inquirer/prompts"; import { getProjectRoot } from "./lib/project.js"; import { updateEnvFile } from "./lib/env.js"; import { readIndex, writeIndex } from "./lib/indexFile.js"; import { showHeader, showTaskDone, showError, showInfo, showFileAction, installDeps, } from "./lib/ui.js"; import { buildDiscoveryModule, wireDiscoveryIntoIndex } from "./lib/codegen.js"; async function main() { showHeader("add-bonjour", "Advertise this app on the local network (Bonjour / mDNS)"); showInfo( "Other devices on the same Wi-Fi/LAN can then reach this app by name " + "(http://<host>.local:<port>) — no hard-coded IPs. Works with Apple Bonjour, " + "Android/Windows/Linux mDNS, and the bonsoir Flutter plugin.", ); const root = getProjectRoot(); const envPath = path.join(root, ".env"); const discoveryPath = path.join(root, "src", "discovery.js"); const name = ( await input({ message: "Service name (blank = app name + hostname):", default: "" }) ).trim(); const type = ( await input({ message: "Service type (without the leading underscore):", default: "http" }) ).trim() || "http"; console.log(); // 1. Write the discovery module from the single source of truth (codegen). It's // deterministic, so re-running just refreshes the file in place. fs.mkdirSync(path.dirname(discoveryPath), { recursive: true }); const existed = fs.existsSync(discoveryPath); fs.writeFileSync(discoveryPath, buildDiscoveryModule(), "utf8"); showFileAction(existed ? "updated" : "created", "src/discovery.js"); // 2. Wire it into index.js (idempotent — a no-op if already wired). try { const before = readIndex(); const after = wireDiscoveryIntoIndex(before); if (after !== before) { writeIndex(after); showFileAction("updated", "index.js"); } else { showInfo("index.js is already wired for discovery — leaving it as is."); } } catch (e) { showInfo( "Could not auto-wire index.js (" + e.message + "). Import { startAdvertising, destroyDiscovery } from './src/discovery.js' " + "and call startAdvertising({ port }) after your server starts listening.", ); } // 3. Configuration in .env. updateEnvFile(envPath, "BONJOUR_ENABLED", "on"); if (name) updateEnvFile(envPath, "BONJOUR_NAME", name); if (type && type !== "http") updateEnvFile(envPath, "BONJOUR_TYPE", type); showFileAction("updated", ".env"); // 4. Dependency (records it in package.json even if the install is offline). await installDeps("bonjour-service"); showTaskDone("Bonjour / mDNS discovery enabled", [ name ? `Service name: ${name}` : "Service name: app name + hostname", `Service type: _${type}._tcp`, "Advertises once the server is listening; sends goodbye packets on clean shutdown", "Browse peers on the network from the /_dev dashboard → Discovery", "Disable anytime with BONJOUR_ENABLED=off in .env", ]); } main().catch((err) => { if (err.name === "ExitPromptError") process.exit(0); showError(err.message); process.exit(1); });