mikser-io 9.73.0 → 9.74.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.
package/app.js CHANGED
@@ -49,8 +49,6 @@ function locate(argv) {
49
49
  longRunning,
50
50
  workingFolder: value('--working-folder', '-i') ?? '.',
51
51
  config: value('--config', '-c') ?? 'mikser.config.js',
52
- // Commander's negated form: `attach` is true unless --no-attach said so.
53
- attach: has('--no-attach') ? false : true,
54
52
  request,
55
53
  }
56
54
  }
@@ -62,18 +60,17 @@ async function main() {
62
60
  // A second server or watcher is the hazard this whole surface exists to
63
61
  // remove, and it is the one shape that cannot be answered by forwarding.
64
62
  // So it stops, rather than silently doing something else.
65
- if (where.attach !== false && where.longRunning) {
63
+ if (where.longRunning) {
66
64
  if (await isInstanceLive(workingFolder)) {
67
65
  process.stderr.write(
68
66
  'mikser: another mikser is already running in this folder, and a server or watcher cannot be '
69
67
  + 'forwarded to it — it would have to open a port on your behalf.\n'
70
- + 'Stop that one, or pass --no-attach to run a second engine here (two engines share the '
71
- + 'catalogue and the output tree, with no lock between them).\n')
68
+ + 'Stop that one first.\n')
72
69
  process.exit(1)
73
70
  }
74
71
  }
75
72
 
76
- if (where.attach !== false && !where.longRunning) {
73
+ if (!where.longRunning) {
77
74
  const code = await forward({
78
75
  workingFolder,
79
76
  config: path.resolve(where.workingFolder, where.config),
@@ -760,8 +760,9 @@ Three things it refuses or reports rather than guessing:
760
760
  to *become* the instance, which is not something a running one can do for
761
761
  you — it would have to open a port in your process. They exit 1 and say so,
762
762
  rather than building and leaving nothing on the port.
763
- - **A folder held by someone else.** `--no-attach` runs a private engine
764
- anyway — for checking that a cold start works — and says the folder is held.
763
+ There is no opt-out. A flag for running a second engine on a held folder
764
+ only ever enabled the accident this surface prevents, and stopping the
765
+ instance serves every case it was reached for.
765
766
 
766
767
  `--tool`, `--tools`, `--verify` and `--explain` forward as well, and for a
767
768
  different reason than builds do. They only read, so running one locally never
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mikser-io",
3
- "version": "9.73.0",
3
+ "version": "9.74.0",
4
4
  "files": [
5
5
  "app.js",
6
6
  "index.js",
package/src/engine.js CHANGED
@@ -386,7 +386,6 @@ export async function setup(options) {
386
386
  runtime.engine.commander?.version(packageInfo.version)
387
387
  .option('-i --working-folder <folder>', 'set mikser working folder', './')
388
388
  .option('-c --config <file>', 'set mikser mikser.config.js location', './mikser.config.js')
389
- .option('--no-attach', 'start a private engine instead of forwarding to the one already running here')
390
389
  .option('-m --mode <mode>', 'set mikser runtime mode', 'development')
391
390
  .option('-r --clear', 'clear current state before execution', false)
392
391
  .option('-o --output-folder <folder>', 'set mikser output folder relative to working folder', 'out')
package/src/instance.js CHANGED
@@ -19,10 +19,12 @@
19
19
  // new to learn and no watermark to reason about — which matters, because a
20
20
  // design that needs discipline from the caller is the one that gets violated.
21
21
  //
22
- // `--no-attach` opts out, for when a fresh process IS the point: checking that
23
- // a cold start works, that startup ordering hides nothing. Named for what it
24
- // switches off rather than for a property of the process — the default is to
25
- // attach, and the flag should say which behaviour is being declined.
22
+ // There is no opt-out. A flag for "run a second engine here anyway" only ever
23
+ // enabled the accident this file exists to prevent — two engines sharing one
24
+ // catalogue and one output tree with no lock between them — and no caller had
25
+ // a reason to want it that a stopped instance would not serve better. An
26
+ // option whose only use is the wrong one is not an escape hatch, it is a trap
27
+ // with a name.
26
28
 
27
29
  import net from 'node:net'
28
30
  import { createHash } from 'node:crypto'
@@ -280,7 +282,7 @@ function refuseConfig(socket, request, wrongConfig) {
280
282
  type: 'refused',
281
283
  reason: `this instance is running ${wrongConfig}, and you asked for ${path.resolve(request.config)}.`,
282
284
  detail: 'Answering would use the wrong config — the accident this refusal exists to prevent. '
283
- + 'Stop that instance, or pass --no-attach to run your own.',
285
+ + 'Stop that instance and run this again.',
284
286
  })
285
287
  }
286
288
 
@@ -341,7 +343,6 @@ async function serveBuild(socket, request, logger) {
341
343
  export function serveInstance() {
342
344
  onLoaded(async () => {
343
345
  if (!runtime.options.watch && !runtime.options.server) return
344
- if (runtime.options.attach === false) return
345
346
  const logger = runtime.engine?.logger
346
347
  const endpoint = socketPath(runtime.options.workingFolder)
347
348
 
@@ -402,53 +403,7 @@ export function serveInstance() {
402
403
 
403
404
  // Say so when a private engine is starting in a folder someone else holds.
404
405
  //
405
- // The local counterpart of the rule already written down for deployments —
406
- // "never run a one-shot mikser command against the deployment" — which existed
407
- // because there was no alternative. There is one now, so this covers what is
408
- // left: --no-attach, and the report-only runs that stay local by design.
409
- //
410
- // A warning rather than a refusal. --no-attach is how you deliberately check
411
- // that a cold start works, and refusing it would take away the escape hatch
412
- // this design depends on having.
413
- export async function warnIfHeld({ workingFolder, attached }) {
414
- const endpoint = socketPath(workingFolder)
415
- if (process.platform !== 'win32' && !existsSync(endpoint)) return false
416
-
417
- const live = await new Promise((resolve) => {
418
- const probe = net.connect(endpoint)
419
- const done = (answer) => { try { probe.destroy() } catch { /* already gone */ } resolve(answer) }
420
- probe.on('connect', () => done(true))
421
- probe.on('error', () => done(false))
422
- setTimeout(() => done(false), 250).unref?.()
423
- })
424
- if (!live) return false
425
-
426
- const logger = runtime.engine?.logger
427
- const message = attached === false
428
- ? 'Another mikser is already running in this folder, and --no-attach means this one will not talk to '
429
- + 'it. Two engines share the catalogue and the output tree with no lock between them; a --clear from '
430
- + 'either is what produces a cold rebuild that renders nothing.'
431
- : 'Another mikser is already running in this folder. This command reads and does not write, so it is '
432
- + 'safe — but it may see a catalogue mid-cycle.'
433
- logger?.warn?.({ code: 'instance-already-running' }, message)
434
- return true
435
- }
436
-
437
406
  // Registered at setup so both halves are wired from one call.
438
407
  export function instanceControl() {
439
408
  serveInstance()
440
- onLoaded(async () => {
441
- // Only --no-attach reaches this now. Everything else either forwarded
442
- // (a build, a report) or refused before setup ran (a second server or
443
- // watcher), so a process that is still here and not attaching is one
444
- // that deliberately opted out — and that is exactly the case worth
445
- // saying something about, long-running or not. The earlier gate
446
- // skipped watch and server, which excluded `--no-attach --server`:
447
- // the very command that puts two engines on one folder.
448
- if (runtime.options.attach !== false) return
449
- await warnIfHeld({
450
- workingFolder: runtime.options.workingFolder,
451
- attached: false,
452
- })
453
- })
454
409
  }