# Node service example


This tour builds a tiny HTTP service from `server.js`. The point is not
to mimic a full Node packaging API; it is to show how a builder can name
its domain concepts and then expose several views of the same build.

The worked artifact is a runnable package with a copied service source,
generated package metadata, a wrapper script, an HTTP service descriptor,
a runtime unit declaration, and a materialization plan.

## Start from the artifact

The source fixture is one file: `node-service/server.js`. The builder
turns that file into a runnable tree:

- `bin/node-service-demo` starts the service with Node.
- `lib/node-service-demo/server.js` contains the copied source.
- `share/node-service-demo/package.json` is generated from the typed
  builder spec.
- the runtime view describes the service as HTTP on port 3000 with a
  `/health` endpoint.

## Source files

These pages are the complete source for the worked example: the builder module plus the files it consumes.

- [Node service builder module](/metaBuilder/examples/node-service/source/builder.nix) - Source for the Node service builder constructor and worked demo program.
- [server.js](/metaBuilder/examples/node-service/source/server.js) - HTTP service fixture copied into the materialized Node demo package.

## Builder vocabulary

`NodeServiceBuilder` ornaments the generic `BuilderSpec` with the
fields a service builder cares about: runtime version, entrypoint,
package manager, script table, test command, service descriptor, and
runtime operations. The constructor keeps the public surface small.

```nix
nodeService {
  name = "node-service-demo";
  source = ./node-service/server.js;
}
```

## Program walkthrough

The constructor lowers the service spec into an internalized program.
The builder-facing operations read the source, declare `node` and
`bash`, generate `package.json`, run a syntax check, install the
runnable tree, emit metadata, and declare the materialized outputs.

The runtime operations are part of the same program. They declare the
lifecycle capability set, the HTTP protocol, the concrete service, and
the runtime unit. That is why dependency analysis, dry-run output,
plan-view output, and self-documentation all see the service shape.

## One build, many views

The section below is generated from `mb.program.introspect.run
program`. It is not a hand-written summary. It validates the program,
extracts the dependency graph, renders dry-run and plan-view output,
includes service descriptors, and reports the materialized outputs.

The same internalized program is interpreted several ways.

### Validation

- result: `ok`

### Dependency Graph

- nodes: `5`
- edges: `2`
- services: `1`
- node `tool:node` (tool) package `nodejs`
- node `tool:bash` (tool) package `bash-interactive`
- node `operation:syntax-check` (operation) via `node`
- node `operation:install-service` (operation) via `bash`
- node `service:node-service-demo-service` (service) package `nodejs`
- edge `tool:node` -> `operation:syntax-check` (uses-tool)
- edge `tool:bash` -> `operation:install-service` (uses-tool)

### Dry Run - Builder

- source `server.js`
- tool `node`
- tool `bash`
- write `share/node-service-demo/package.json`
- run `syntax-check` with `node`
- run `install-service` with `bash`
- descriptor `node-service-demo-metadata`
- transform `service-tree` (tree)
- transform `package-json` (json)
- materialize `node-service-demo-artifact` with `runCommand`
- evidence `self-test`

### Dry Run - Runtime

- runtime capability `lifecycle`
- runtime protocol `http`
- runtime service `node-service-demo-service`
- runtime unit `node-service-demo-service`

### Plan View

- write `write:share/node-service-demo/package.json`
- run `syntax-check`
- run `install-service`
- `write:share/node-service-demo/package.json`: `mkdir -p "$(dirname "$out/share/node-service-demo/package.json")"`
- `syntax-check`: `node --check "$pathMap_85e860eb67550a011692fa61e2a4543318fcdb72bf6de38c7f85842029ee99ae"`
- `install-service`: `bash -c 'set -eu`

### Plan Shell Excerpt

```sh
pathMap_85e860eb67550a011692fa61e2a4543318fcdb72bf6de38c7f85842029ee99ae=<source:server.js>
mkdir -p "$(dirname "$out/share/node-service-demo/package.json")"
cat > "$out/share/node-service-demo/package.json" <<'METABUILDER_HEREDOC_83625931feff0ed1f14d2f61a28aea1a87b63276765f4ca0cc2bceddf130aeed'
{"main":"server.js","name":"node-service-demo","private":true,"scripts":{"start":"node server.js","test":"node --check server.js"},"type":"module","version":"0.1.0"}
METABUILDER_HEREDOC_83625931feff0ed1f14d2f61a28aea1a87b63276765f4ca0cc2bceddf130aeed
node --check "$pathMap_85e860eb67550a011692fa61e2a4543318fcdb72bf6de38c7f85842029ee99ae"
bash -c 'set -eu
src="$1"
mkdir -p "'"$out"'/bin" "'"$out"'/lib/node-service-demo" "'"$out"'/share/node-service-demo"
cp "$src" "'"$out"'/lib/node-service-demo/server.js"
```

### Runtime Services

- service `node-service-demo-service` exposes `http/TCP/JSON PORT:3000`; capabilities `start`, `stop`, `health`

### Descriptors

- descriptor `node-service-demo-metadata` (payload keys `entrypoint`, `healthPath`, `kind`, `packageManager`, `port`, `runtimeVersion`)

### Builder Self-Documentation

- documented operations: `15`
- runtime services: `1`

### Materialized Outputs

- service-tree -> $out (tree)
- package-json -> share/node-service-demo/package.json (json)

### Materialization

- derivation: `node-service-demo-artifact`
- outputs: `2`
- runtime artifacts: `1`
- service `node-service-demo-service`

### Substrates

- dockerfile: `supported`
- shell: `supported`

