nervur 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/nervur.js +41 -11
  2. package/package.json +1 -1
package/nervur.js CHANGED
@@ -9,7 +9,7 @@ import { spawnSync } from 'node:child_process'
9
9
  import { createHash } from 'node:crypto'
10
10
  import { existsSync, mkdirSync, readFileSync, realpathSync, rmSync, writeFileSync } from 'node:fs'
11
11
  import { homedir } from 'node:os'
12
- import { dirname, join } from 'node:path'
12
+ import { dirname, join, relative } from 'node:path'
13
13
  import { request as httpsRequest } from 'node:https'
14
14
  import { pathToFileURL } from 'node:url'
15
15
  import { resolveTemplate } from '@nervur-org/kit/templates.js'
@@ -103,7 +103,7 @@ const localOk = async (url) => {
103
103
  // scheme, and one without it still comes up on localhost. Bounded but generous:
104
104
  // the first boot installs node_modules (a native module) inside the container,
105
105
  // which takes a few minutes, so the wait prints progress rather than looking hung.
106
- async function knock({ localUrl, domain, ca, ms = 300_000 }) {
106
+ async function knock({ localUrl, domain, ca, ms = 600_000 }) {
107
107
  const until = Date.now() + ms
108
108
  let noted = 0
109
109
  for (;;) {
@@ -214,13 +214,43 @@ async function main() {
214
214
  // and any contributor testing `install`, points the client at their OWN carcass
215
215
  // rather than the dev bench's). Absent NERVUR_PORT, the dev bench's config.face.port
216
216
  // is the convenience default; absent both, a published install's own default (4000).
217
+ // Reached at 127.0.0.1, never `localhost`: the compose binds IPv4 loopback
218
+ // only, and macOS launchd holds ::1 listeners (AirPlay on 5000) that accept
219
+ // and hang a localhost knock. Host ports must also dodge the WHATWG fetch
220
+ // bad-ports list (6000/X11 and kin) — node's fetch refuses those outright.
217
221
  const faceUrl = process.env.NERVUR_PORT
218
- ? `http://localhost:${process.env.NERVUR_PORT}`
219
- : config.face?.port
220
- ? `http://localhost:${config.face.port}`
221
- : 'http://localhost:4000'
222
+ ? `http://127.0.0.1:${process.env.NERVUR_PORT}`
223
+ : (config.hostPorts?.face ?? config.face?.port)
224
+ ? `http://127.0.0.1:${config.hostPorts?.face ?? config.face.port}`
225
+ : 'http://127.0.0.1:4000'
222
226
  const face = () => faceUrl
223
227
 
228
+ // A config without project/hostPorts/domains (the published install path)
229
+ // gets none of these vars — the compose defaults hold.
230
+ const composeEnv = () => {
231
+ const env = { ...process.env }
232
+ if (config.project) env.COMPOSE_PROJECT_NAME = config.project
233
+ if (config.domains) env.COMPOSE_PROFILES = 'door'
234
+ const seam = {
235
+ face: 'FACE',
236
+ console: 'CONSOLE',
237
+ faces: 'FACES',
238
+ ctlKeeper: 'CTL_KEEPER',
239
+ ctlUpsy: 'CTL_UPSY',
240
+ ctlFedexy: 'CTL_FEDEXY',
241
+ dpUpsy: 'DP_UPSY',
242
+ dpFedexy1: 'DP_FEDEXY1',
243
+ dpFedexy2: 'DP_FEDEXY2'
244
+ }
245
+ for (const [key, name] of Object.entries(seam))
246
+ if (config.hostPorts?.[key] != null) env[`NERVUR_HOST_${name}`] = String(config.hostPorts[key])
247
+ if (config.compose) {
248
+ const rel = configPath.startsWith('/') ? relative(process.cwd(), configPath) : configPath
249
+ env.NERVUR_GROUND_IN = `/app/${rel.replace(/^\.\//, '')}`
250
+ }
251
+ return env
252
+ }
253
+
224
254
  // `--as <name>` is a global flag — it rides before OR after the verb (`nervur
225
255
  // --as acme add empty` and `nervur add empty --as acme` both work), so pull it
226
256
  // out of the raw argv before the verb is read off position 0.
@@ -315,7 +345,7 @@ async function main() {
315
345
  }
316
346
  })
317
347
 
318
- const localUrl = `http://localhost:${port}`
348
+ const localUrl = `http://127.0.0.1:${port}`
319
349
  await knock({ localUrl: `${localUrl}/health` })
320
350
  print(await getJson(`${localUrl}/whoami`))
321
351
 
@@ -359,7 +389,7 @@ async function main() {
359
389
  process.exit(1)
360
390
  }
361
391
  if (config.certs) sh('bash', [config.certs])
362
- if (config.compose) sh('docker', ['compose', '-f', config.compose, 'up', '-d'])
392
+ if (config.compose) sh('docker', ['compose', '-f', config.compose, 'up', '-d'], { env: composeEnv() })
363
393
  const ca = readCA(config)
364
394
  // Door open: knock the domain first, so a bench with hosts run reports through
365
395
  // the real URL scheme (slice-2 behavior). Door closed: localhost only.
@@ -384,17 +414,17 @@ async function main() {
384
414
  // the domain door.
385
415
  console.log(
386
416
  banner('ground is standing', [
387
- ['console', cyan(`http://localhost:${config.console?.port ?? 4200}`), 'open in your browser']
417
+ ['console', cyan(`http://localhost:${config.hostPorts?.console ?? config.console?.port ?? 4200}`), 'open in your browser']
388
418
  ]) + `\n ${dim(`api ${via === 'domain' ? `https://${faceDomain}` : face()}`)}\n`
389
419
  )
390
420
  break
391
421
  }
392
422
  case 'down':
393
- if (config.compose) sh('docker', ['compose', '-f', config.compose, 'down'])
423
+ if (config.compose) sh('docker', ['compose', '-f', config.compose, 'down'], { env: composeEnv() })
394
424
  console.log('down')
395
425
  break
396
426
  case 'reset':
397
- if (config.compose) sh('docker', ['compose', '-f', config.compose, 'down', '-v'])
427
+ if (config.compose) sh('docker', ['compose', '-f', config.compose, 'down', '-v'], { env: composeEnv() })
398
428
  for (const dir of config.dataDirs ?? []) rmSync(dir, { recursive: true, force: true })
399
429
  console.log('reset')
400
430
  break
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nervur",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "The nervur CLI — a client of a running carcass, never the runtime (papers/host.md).",
5
5
  "type": "module",
6
6
  "bin": {