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
15 changes: 13 additions & 2 deletions cmd/add/solution_playground.go
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ FRONTEND=${endpoint:%s/web/http}
// playgroundMakefile writes the run line, whose one non-obvious part is that
// authority/edge is NAMED. Nothing starts it otherwise.
func playgroundMakefile(name string) string {
return fmt.Sprintf(`.PHONY: playground
return fmt.Sprintf(`.PHONY: playground remote

# %s on the development authority, as a solution runs in a cell with no saas
# host: the authority's edge is the one origin the browser opens and signs a
Expand All @@ -204,8 +204,19 @@ func playgroundMakefile(name string) string {
# origin that can sign anyone in.
PLAYGROUND_SERVICES = authority/edge %s/web %s/backend

playground:
# THE REMOTE IS BUILT FIRST, and that is not a convenience. The solution
# runtime serves /assets/ from ASSETS_DIR, which defaults to
# ../fe-remote/dist relative to the backend — so with no build there, the
# backend answers 404 for /assets/mf-manifest.json, the manifest it
# advertises in /.well-known/solution.json, and a host can federate nothing.
# The shell also installs the remote as a copy, so it needs it built.
playground: remote
cd %s && codefly run service $(PLAYGROUND_SERVICES) --env local

.PHONY: remote
remote:
cd services/fe-remote && npm install --no-audit --no-fund && npm run build
test -f services/fe-remote/dist/mf-manifest.json
`, titleFromName(name), name, name, playgroundDir)
}

Expand Down
22 changes: 22 additions & 0 deletions cmd/add/solution_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -555,3 +555,25 @@ func TestTheContractDeclaresARoleBesidesInstaller(t *testing.T) {
t.Fatalf("the contract must declare installer and viewer, got %v", names)
}
}

// TestThePlaygroundBuildsTheRemoteFirst. The solution runtime serves /assets/
// from ASSETS_DIR, which defaults to ../fe-remote/dist relative to the
// backend. With nothing built there the backend answers 404 for
// /assets/mf-manifest.json — the manifest it advertises in
// /.well-known/solution.json — and a host can federate nothing. The fleet's
// own playground builds the remote before the run for exactly this reason.
func TestThePlaygroundBuildsTheRemoteFirst(t *testing.T) {
makefile := playgroundMakefile("notes")
if !strings.Contains(makefile, "playground: remote") {
t.Fatalf("the playground must build the remote first:\n%s", makefile)
}
for _, required := range []string{
"cd services/fe-remote && npm install",
"npm run build",
"test -f services/fe-remote/dist/mf-manifest.json",
} {
if !strings.Contains(makefile, required) {
t.Fatalf("the remote target must contain %q", required)
}
}
}
11 changes: 9 additions & 2 deletions docs/commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -2435,8 +2435,9 @@ What it creates:
`services/fe-remote` — the `./Page` remote itself — is written by the solution
agent, not by this command: it is an npm package, not a Codefly service.

**Running it.** `make playground` starts the development authority and this
solution, and prints the one address a browser opens:
**Running it.** `make playground` builds the page's remote, starts the
development authority and this solution, and prints the one address a browser
opens:

```
edge listening on :14581, routing 1 module(s)
Expand All @@ -2450,6 +2451,12 @@ not behind its sign-in edge") and the authority's REST port (every browser
path 404s). In a cell the host's gateway plays the edge's part; the playground
is local only.

The remote is built **before** the run, and that is load-bearing: the solution
runtime serves `/assets/` from `ASSETS_DIR`, which defaults to
`../fe-remote/dist` relative to the backend. With nothing built there the
backend answers 404 for `/assets/mf-manifest.json` — the manifest it
advertises in `/.well-known/solution.json` — and a host can federate nothing.

Sign in as any of the fixture's acme people in a team — `maya`, `remi`,
`alex`, `dev` — and the solution's route answers:

Expand Down
Loading