The runtime knows no language: the build makes each served entrypoint executable. For a TypeScript bundle that is <entry>.serve.mjs, which imports the entrypoint and serves what it registered over MCP on stdio through the bundle's own SDK. The build records its launchers on the bundle, and the composer names the launcher where a build wrote one and the entrypoint where it did not, so bundles built before this keep serving until they are rebuilt.
50 lines
1.7 KiB
Go
50 lines
1.7 KiB
Go
package builder
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/novox/mesh-controller/internal/catalogue"
|
|
)
|
|
|
|
// novox/hq ADR 0193: every entrypoint the runtime may serve is executable, and the runtime knows no
|
|
// language — so a TypeScript bundle carries a launcher beside each entrypoint.
|
|
func TestATypeScriptBundleCarriesAnExecutableLauncherBesideEachEntrypoint(t *testing.T) {
|
|
root := t.TempDir()
|
|
chain, err := ToolchainFor("typescript")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
got, err := writeLaunchers(root, chain, catalogue.Artifact{Name: "tools", Kind: catalogue.ArtifactBundle,
|
|
Language: "typescript", Entrypoints: []string{"tools/index.js", "index.js"}})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if got["tools/index.js"] != "tools/index.serve.mjs" || got["index.js"] != "index.serve.mjs" {
|
|
t.Fatalf("launchers: %v", got)
|
|
}
|
|
path := filepath.Join(root, "tools", "index.serve.mjs")
|
|
info, err := os.Stat(path)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if info.Mode().Perm() != 0o755 {
|
|
t.Errorf("the launcher is %v, not executable 0755", info.Mode().Perm())
|
|
}
|
|
body, _ := os.ReadFile(path)
|
|
for _, want := range []string{"#!/usr/bin/env node\n", `from "@novox/mesh-sdk/stdio"`, `await import("./index.js")`, "serveRegisteredOverStdio()"} {
|
|
if !strings.Contains(string(body), want) {
|
|
t.Errorf("the launcher lacks %q:\n%s", want, body)
|
|
}
|
|
}
|
|
|
|
// A compiled language's build is executable already: no launcher.
|
|
goChain, _ := ToolchainFor("go")
|
|
none, err := writeLaunchers(t.TempDir(), goChain, catalogue.Artifact{Name: "tools", Kind: catalogue.ArtifactBundle, Language: "go"})
|
|
if err != nil || len(none) != 0 {
|
|
t.Errorf("a Go bundle was given launchers: %v %v", none, err)
|
|
}
|
|
}
|