goke 6.3.2 → 6.5.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/README.md CHANGED
@@ -15,6 +15,7 @@
15
15
  - **Yet so powerful**. Enable features like default command, git-like subcommands, validation for required arguments and options, variadic arguments, dot-nested options, automated help message generation and so on.
16
16
  - **Space-separated subcommands**: Support multi-word commands like `mcp login`, `git remote add`.
17
17
  - **Schema-based type coercion**: Use Zod, Valibot, ArkType, or plain JSON Schema for automatic type coercion and TypeScript type inference. Description and default values are extracted from the schema automatically.
18
+ - **Injected execution context**: Prefer `{ fs, console, process }` in actions and middleware for portable storage, output, and runtime metadata across Node.js, tests, and JustBash.
18
19
  - **Type-safe middleware**: Register `.use()` callbacks that run before commands with full type inference from global options.
19
20
  - **Developer friendly**. Written in TypeScript.
20
21
 
@@ -43,8 +44,8 @@ cli.option(
43
44
  )
44
45
  cli.option('--name <name>', 'Provide your name')
45
46
 
46
- cli.command('lint [...files]', 'Lint files').action((files, options) => {
47
- console.log(files, options)
47
+ cli.command('lint [...files]', 'Lint files').action((files, options, { console, process }) => {
48
+ console.log(files, options, process.cwd)
48
49
  })
49
50
 
50
51
  cli
@@ -52,8 +53,8 @@ cli
52
53
  .option('--minify', 'Minify output')
53
54
  .example('build src/index.ts')
54
55
  .example('build src/index.ts --minify')
55
- .action(async (entry, options) => { // options is type safe! no need to type it
56
- console.log(entry, options)
56
+ .action(async (entry, options, { console, process }) => { // options is type safe! no need to type it
57
+ console.log(entry, options, process.env.NODE_ENV)
57
58
  })
58
59
 
59
60
  cli.example((bin) => `${bin} lint src/**/*.ts`)
@@ -132,8 +133,8 @@ cli
132
133
  .option('--channel <name>', 'Target channel: stable, beta, alpha')
133
134
  .option('--notes-file <path>', 'Markdown file used as release notes')
134
135
  .option('--dry-run', 'Preview every step without publishing')
135
- .action((version, options) => {
136
- console.log('release', version, options)
136
+ .action((version, options, { console, process }) => {
137
+ console.log('release', version, options, process.cwd)
137
138
  })
138
139
 
139
140
  cli
@@ -158,8 +159,8 @@ cli
158
159
  .option('--target <migration>', 'Apply up to a specific migration id')
159
160
  .option('--dry-run', 'Print plan only, do not execute SQL')
160
161
  .option('--verbose', 'Show each executed statement')
161
- .action((options) => {
162
- console.log('migrate', options)
162
+ .action((options, { console, process }) => {
163
+ console.log('migrate', options, process.stdin)
163
164
  })
164
165
 
165
166
  cli.help()
@@ -298,39 +299,39 @@ cli
298
299
  z.string().default('production').describe('Target environment'),
299
300
  )
300
301
  .option('--dry-run', 'Preview without deploying')
301
- .action((options) => {
302
- console.log(`Deploying to ${options.env}...`)
302
+ .action((options, { console, process }) => {
303
+ console.log(`Deploying to ${options.env} from ${process.cwd}...`)
303
304
  })
304
305
 
305
306
  // Subcommands
306
307
  cli
307
308
  .command('init', 'Initialize a new project')
308
309
  .option('--template <template>', 'Project template')
309
- .action((options) => {
310
- console.log('Initializing project...')
310
+ .action((options, { console, process }) => {
311
+ console.log('Initializing project in', process.cwd)
311
312
  })
312
313
 
313
- cli.command('login', 'Authenticate with the server').action(() => {
314
- console.log('Opening browser for login...')
314
+ cli.command('login', 'Authenticate with the server').action((options, { console, process }) => {
315
+ console.log('Opening browser for login from', process.cwd)
315
316
  })
316
317
 
317
- cli.command('logout', 'Clear saved credentials').action(() => {
318
- console.log('Logged out')
318
+ cli.command('logout', 'Clear saved credentials').action((options, { console, process }) => {
319
+ console.log('Logged out', process.env.USER)
319
320
  })
320
321
 
321
322
  cli
322
323
  .command('status', 'Show deployment status')
323
324
  .option('--json', 'Output as JSON')
324
- .action((options) => {
325
- console.log('Fetching status...')
325
+ .action((options, { console, process }) => {
326
+ console.log('Fetching status from', process.cwd)
326
327
  })
327
328
 
328
329
  cli
329
330
  .command('logs <deploymentId>', 'Stream logs for a deployment')
330
331
  .option('--follow', 'Follow log output')
331
332
  .option('--lines <n>', z.number().default(100).describe('Number of lines'))
332
- .action((deploymentId, options) => {
333
- console.log(`Streaming logs for ${deploymentId}...`)
333
+ .action((deploymentId, options, { console, process }) => {
334
+ console.log(`Streaming logs for ${deploymentId} from ${process.cwd}...`)
334
335
  })
335
336
 
336
337
  cli.help()
@@ -351,8 +352,72 @@ deploy --help # shows all commands
351
352
 
352
353
  Global options are defined on the CLI instance and apply to all commands. Use `.use()` to register middleware that runs before any command action — useful for reacting to global options like setting up logging, initializing state, or configuring services.
353
354
 
355
+ Prefer the injected `{ fs, console, process }` argument over global `console`, `process.exit`, or direct `node:fs/promises` imports. It keeps commands easier to test and lets the same command code run inside alternate runtimes like JustBash.
356
+
357
+ `process.cwd`, `process.stdin`, and `process.env` come from the active runtime:
358
+
359
+ - In normal Node.js runs, `process.cwd` and `process.env` reflect the host process, while `process.stdin` defaults to an empty string unless you inject it yourself.
360
+ - In JustBash runs, those same fields are populated from the sandbox execution context.
361
+
354
362
  Middleware runs in registration order, after option parsing and validation, but before the matched command's `.action()` callback.
355
363
 
364
+ ### Filesystem Access
365
+
366
+ The injected `fs` object is the recommended way to read or write CLI state.
367
+
368
+ - In normal Node.js runs, `fs` defaults to `node:fs/promises`
369
+ - In JustBash runs, `goke` swaps in a compatible adapter over the JustBash virtual filesystem
370
+
371
+ This makes storage-style commands work in both environments without branching on runtime details.
372
+
373
+ ```ts
374
+ cli
375
+ .command('login', 'Save auth token')
376
+ .option('--token <token>', z.string().describe('Auth token'))
377
+ .action(async (options, { fs, console, process }) => {
378
+ await fs.mkdir('.mycli', { recursive: true })
379
+ await fs.writeFile('.mycli/auth.json', JSON.stringify({ token: options.token }), 'utf8')
380
+ console.log('saved credentials in', process.cwd)
381
+ })
382
+
383
+ cli
384
+ .command('whoami', 'Read saved auth token')
385
+ .action(async (options, { fs, console, process }) => {
386
+ const auth = await fs.readFile('.mycli/auth.json', 'utf8')
387
+ console.log(auth, process.env.USER)
388
+ })
389
+ ```
390
+
391
+ Prefer injected `fs` for CLI storage instead of importing `node:fs/promises` directly inside actions. That keeps the command portable to JustBash and easier to test.
392
+
393
+ `goke` also exports the runtime types, so helper functions can use dependency injection without reaching for globals:
394
+
395
+ ```ts
396
+ import { goke } from 'goke'
397
+ import type { GokeFs, GokeProcess } from 'goke'
398
+
399
+ async function saveAuthToken(args: {
400
+ fs: GokeFs
401
+ process: GokeProcess
402
+ token: string
403
+ }) {
404
+ await args.fs.mkdir('.mycli', { recursive: true })
405
+ await args.fs.writeFile('.mycli/auth.json', JSON.stringify({
406
+ token,
407
+ cwd: args.process.cwd,
408
+ }), 'utf8')
409
+ }
410
+
411
+ const cli = goke('mycli')
412
+
413
+ cli
414
+ .command('login <token>', 'Save auth token')
415
+ .action(async (token, options, { fs, process, console }) => {
416
+ await saveAuthToken({ fs, process, token })
417
+ console.log('saved credentials')
418
+ })
419
+ ```
420
+
356
421
  ```ts
357
422
  import { goke } from 'goke'
358
423
  import { z } from 'zod'
@@ -362,25 +427,25 @@ const cli = goke('mycli')
362
427
  cli
363
428
  .option('--verbose', z.boolean().default(false).describe('Enable verbose logging'))
364
429
  .option('--api-url [url]', z.string().default('https://api.example.com').describe('API base URL'))
365
- .use((options) => {
430
+ .use((options, { console, process }) => {
366
431
  // options.verbose and options.apiUrl are fully typed here
367
432
  if (options.verbose) {
368
- process.env.LOG_LEVEL = 'debug'
433
+ console.log('verbose mode enabled in', process.cwd)
369
434
  }
370
435
  })
371
436
 
372
437
  cli
373
438
  .command('deploy <env>', 'Deploy to an environment')
374
439
  .option('--dry-run', 'Preview without deploying')
375
- .action((env, options) => {
440
+ .action((env, options, { console, process }) => {
376
441
  // options includes both command options (dryRun) and global options (verbose, apiUrl)
377
- console.log(`Deploying to ${env} via ${options.apiUrl}`)
442
+ console.log(`Deploying to ${env} via ${options.apiUrl} from ${process.cwd}`)
378
443
  })
379
444
 
380
445
  cli
381
446
  .command('status', 'Show deployment status')
382
- .action((options) => {
383
- console.log('Checking status...')
447
+ .action((options, { console, process }) => {
448
+ console.log('Checking status...', process.stdin)
384
449
  })
385
450
 
386
451
  cli.help()
@@ -392,14 +457,19 @@ Type safety is positional — each `.use()` callback only sees options declared
392
457
  ```ts
393
458
  cli
394
459
  .option('--verbose', z.boolean().default(false).describe('Verbose'))
395
- .use((options) => {
460
+ .use((options, { process }) => {
396
461
  options.verbose // boolean — typed
462
+ process.argv // string[] — typed
463
+ process.cwd // string — typed
464
+ process.env // Record<string, string> — typed
465
+ process.stdin // string — typed
397
466
  options.port // TypeScript error — not declared yet
398
467
  })
399
468
  .option('--port <port>', z.number().describe('Port'))
400
- .use((options) => {
469
+ .use((options, { console, process }) => {
401
470
  options.verbose // boolean — still visible
402
471
  options.port // number — now visible
472
+ console.error('ready', process.cwd)
403
473
  })
404
474
  ```
405
475
 
@@ -408,9 +478,10 @@ Middleware supports async functions. If any middleware is async, the remaining m
408
478
  ```ts
409
479
  cli
410
480
  .option('--token <token>', z.string().describe('API token'))
411
- .use(async (options) => {
481
+ .use(async (options, { console, process }) => {
412
482
  const client = await connectToApi(options.token)
413
483
  globalState.client = client
484
+ console.log('connected', process.env.NODE_ENV)
414
485
  })
415
486
  ```
416
487
 
@@ -426,8 +497,8 @@ const cli = goke()
426
497
  cli
427
498
  .command('rm <dir>', 'Remove a dir')
428
499
  .option('-r, --recursive', 'Remove recursively')
429
- .action((dir, options) => {
430
- console.log('remove ' + dir + (options.recursive ? ' recursively' : ''))
500
+ .action((dir, options, { console, process }) => {
501
+ console.log('remove ' + dir + (options.recursive ? ' recursively' : ''), process.cwd)
431
502
  })
432
503
 
433
504
  cli.help()
@@ -444,18 +515,18 @@ import { goke } from 'goke'
444
515
 
445
516
  const cli = goke('mycli')
446
517
 
447
- cli.command('mcp login <url>', 'Login to MCP server').action((url) => {
448
- console.log('Logging in to', url)
518
+ cli.command('mcp login <url>', 'Login to MCP server').action((url, options, { console, process }) => {
519
+ console.log('Logging in to', url, 'from', process.cwd)
449
520
  })
450
521
 
451
- cli.command('mcp logout', 'Logout from MCP server').action(() => {
452
- console.log('Logged out')
522
+ cli.command('mcp logout', 'Logout from MCP server').action((options, { console, process }) => {
523
+ console.log('Logged out', process.env.USER)
453
524
  })
454
525
 
455
526
  cli
456
527
  .command('git remote add <name> <url>', 'Add a git remote')
457
- .action((name, url) => {
458
- console.log('Adding remote', name, url)
528
+ .action((name, url, options, { console, process }) => {
529
+ console.log('Adding remote', name, url, 'from', process.cwd)
459
530
  })
460
531
 
461
532
  cli.help()
@@ -479,9 +550,9 @@ cli
479
550
  .option('--workers <workers>', z.int().describe('Worker count'))
480
551
  .option('--tags <tag>', z.array(z.string()).describe('Tags (repeatable)'))
481
552
  .option('--verbose', 'Verbose output')
482
- .action((options) => {
553
+ .action((options, { console, process }) => {
483
554
  // options.port is number, options.host is string, etc.
484
- console.log(options)
555
+ console.log(options, process.env.NODE_ENV)
485
556
  })
486
557
 
487
558
  cli.parse()
@@ -510,9 +581,9 @@ cli
510
581
  .option('--old-port <port>', z.number().meta({ deprecated: true, description: 'Use --port instead' }))
511
582
  // Current option: visible in help
512
583
  .option('--port <port>', z.number().describe('Port number'))
513
- .action((options) => {
584
+ .action((options, { console, process }) => {
514
585
  const port = options.port ?? options.oldPort
515
- console.log('Starting on port', port)
586
+ console.log('Starting on port', port, 'from', process.cwd)
516
587
  })
517
588
 
518
589
  cli.help()
@@ -548,10 +619,10 @@ The last argument of a command can be variadic. To make an argument variadic you
548
619
  cli
549
620
  .command('build <entry> [...otherFiles]', 'Build your app')
550
621
  .option('--foo', 'Foo option')
551
- .action((entry, otherFiles, options) => {
622
+ .action((entry, otherFiles, options, { console, process }) => {
552
623
  console.log(entry)
553
624
  console.log(otherFiles)
554
- console.log(options)
625
+ console.log(options, process.stdin)
555
626
  })
556
627
  ```
557
628
 
@@ -606,8 +677,8 @@ cli
606
677
  .command('build', 'desc')
607
678
  .option('--env <env>', 'Set envs')
608
679
  .example('--env.API_SECRET xxx')
609
- .action((options) => {
610
- console.log(options)
680
+ .action((options, { console, process }) => {
681
+ console.log(options, process.env.API_SECRET)
611
682
  })
612
683
  ```
613
684
 
@@ -619,9 +690,9 @@ Register a command that will be used when no other command is matched.
619
690
  cli
620
691
  .command('[...files]', 'Build files')
621
692
  .option('--minimize', 'Minimize output')
622
- .action((files, options) => {
693
+ .action((files, options, { console, process }) => {
623
694
  console.log(files)
624
- console.log(options.minimize)
695
+ console.log(options.minimize, process.cwd)
625
696
  })
626
697
  ```
627
698
 
@@ -634,11 +705,46 @@ try {
634
705
  cli.parse(process.argv, { run: false })
635
706
  await cli.runMatchedCommand()
636
707
  } catch (error) {
637
- console.error(error.stack)
708
+ const message = error instanceof Error ? error.stack : String(error)
709
+ process.stderr.write(String(message) + '\n')
638
710
  process.exit(1)
639
711
  }
640
712
  ```
641
713
 
714
+ ### Testing with mocked console and exit
715
+
716
+ Because goke derives its injected `{ fs, console, process }` from the CLI's configured runtime dependencies, tests can override them directly and assert on the calls.
717
+
718
+ ```ts
719
+ import { describe, expect, test, vi } from 'vitest'
720
+ import { goke, GokeProcessExit } from 'goke'
721
+
722
+ describe('deploy command', () => {
723
+ test('writes output and exits with injected mocks', () => {
724
+ const stdout = { write: vi.fn<(data: string) => void>() }
725
+ const stderr = { write: vi.fn<(data: string) => void>() }
726
+ const exit = vi.fn<(code: number) => void>()
727
+
728
+ const cli = goke('acme', { stdout, stderr, exit })
729
+
730
+ cli
731
+ .command('deploy', 'Deploy the project')
732
+ .action((options, { console, process }) => {
733
+ console.log('deploying')
734
+ process.exit(2)
735
+ })
736
+
737
+ expect(() => {
738
+ cli.parse(['node', 'acme', 'deploy'], { run: true })
739
+ }).toThrow(GokeProcessExit)
740
+
741
+ expect(stdout.write).toHaveBeenCalledWith('deploying\n')
742
+ expect(exit).toHaveBeenCalledWith(2)
743
+ expect(stderr.write).not.toHaveBeenCalled()
744
+ })
745
+ })
746
+ ```
747
+
642
748
  ### With TypeScript
643
749
 
644
750
  ```ts
@@ -659,11 +765,11 @@ cli
659
765
  .command('serve <entry>', 'Start the app')
660
766
  .option('--port <port>', z.number().default(3000).describe('Port number'))
661
767
  .option('--watch', 'Watch files')
662
- .action((entry, options) => {
768
+ .action((entry, options, { console, process }) => {
663
769
  // entry: string
664
770
  // options.port: number
665
771
  // options.watch: boolean
666
- console.log(entry, options.port, options.watch)
772
+ console.log(entry, options.port, options.watch, process.cwd)
667
773
  })
668
774
  ```
669
775
 
@@ -677,6 +783,33 @@ import { openInBrowser } from 'goke'
677
783
  openInBrowser('https://example.com/dashboard')
678
784
  ```
679
785
 
786
+ ### Expose a goke CLI to JustBash
787
+
788
+ Use `cli.createJustBashCommand()` to expose a goke CLI as a single JustBash custom command. JustBash command names are single-token executables, but the goke CLI behind them can still use multi-word subcommands like `child commandwithspaces`.
789
+
790
+ ```ts
791
+ import { goke } from 'goke'
792
+ import { z } from 'zod'
793
+ import { Bash } from 'just-bash'
794
+
795
+ const cli = goke('parent')
796
+
797
+ cli
798
+ .command('child commandwithspaces', 'Run nested command')
799
+ .option('--name <name>', z.string().describe('Name'))
800
+ .action((options, { console, process }) => {
801
+ console.log(`hello ${options.name} from ${process.cwd}`)
802
+ })
803
+
804
+ const bash = new Bash({
805
+ customCommands: [await cli.createJustBashCommand()],
806
+ })
807
+
808
+ await bash.exec('parent child commandwithspaces --name Tommy')
809
+ ```
810
+
811
+ Prefer the injected `{ fs, console, process }` helpers in command implementations so the same command code works cleanly both in the regular CLI runtime and through the JustBash bridge. The injected `fs` defaults to Node `fs/promises`, and `process.cwd` / `process.env` / `process.stdin` reflect host values in Node but sandbox values inside `createJustBashCommand()`.
812
+
680
813
  ## References
681
814
 
682
815
  ### CLI Instance
@@ -712,9 +845,9 @@ Add a global option. The second argument is either:
712
845
 
713
846
  #### cli.use(callback)
714
847
 
715
- - Type: `(callback: (options: Opts) => void | Promise<void>) => CLI`
848
+ - Type: `(callback: (options: Opts, { fs, console, process }) => void | Promise<void>) => CLI`
716
849
 
717
- Register a middleware function that runs before the matched command action. Middleware runs in registration order, after option parsing and validation. The callback receives the parsed global options, typed according to all `.option()` calls that precede the `.use()` in the chain.
850
+ Register a middleware function that runs before the matched command action. Middleware runs in registration order, after option parsing and validation. The callback receives the parsed global options, typed according to all `.option()` calls that precede the `.use()` in the chain, plus an injected `{ fs, console, process }` helper object.
718
851
 
719
852
  #### cli.parse(argv?)
720
853
 
@@ -768,6 +901,8 @@ Basically the same as `cli.option` but this adds the option to specific command.
768
901
 
769
902
  - Type: `(callback: ActionCallback) => Command`
770
903
 
904
+ Command callbacks receive positional args first, then parsed options, then an injected `{ fs, console, process }` object. Prefer those injected helpers over global `console`, `process.exit`, and direct `node:fs/promises` imports so commands stay easier to test and can run inside alternate runtimes like JustBash.
905
+
771
906
  #### command.alias(name)
772
907
 
773
908
  - Type: `(name: string) => Command`
@@ -798,7 +933,7 @@ cli.on('command:!', () => {
798
933
  })
799
934
 
800
935
  cli.on('command:*', () => {
801
- console.error('Invalid command: %s', cli.args.join(' '))
936
+ process.stderr.write(`Invalid command: ${cli.args.join(' ')}\n`)
802
937
  process.exit(1)
803
938
  })
804
939
  ```
@@ -2,6 +2,9 @@ import { describe, test, expect } from 'vitest';
2
2
  import goke, { createConsole } from '../index.js';
3
3
  import { coerceBySchema } from '../coerce.js';
4
4
  import { z } from 'zod';
5
+ import { mkdtemp, readFile, rm } from 'node:fs/promises';
6
+ import { tmpdir } from 'node:os';
7
+ import { join } from 'node:path';
5
8
  const ANSI_RE = /\x1B\[[0-9;]*m/g;
6
9
  const stripAnsi = (text) => text.replace(ANSI_RE, '');
7
10
  /**
@@ -129,6 +132,83 @@ describe('error formatting', () => {
129
132
  expect(text).toMatch(/at /);
130
133
  });
131
134
  });
135
+ describe('injected fs', () => {
136
+ test('command actions can use the default node fs for cli storage', async () => {
137
+ const stdout = createTestOutputStream();
138
+ const cli = gokeTestable('mycli', { stdout });
139
+ const originalCwd = process.cwd();
140
+ const tempDir = await mkdtemp(join(tmpdir(), 'goke-fs-'));
141
+ try {
142
+ process.chdir(tempDir);
143
+ cli
144
+ .command('login', 'Persist login state')
145
+ .option('--token <token>', z.string().describe('Token'))
146
+ .action(async (options, { fs, console }) => {
147
+ await fs.mkdir('.mycli', { recursive: true });
148
+ await fs.writeFile('.mycli/auth.json', JSON.stringify({ token: options.token }), 'utf8');
149
+ console.log('saved credentials');
150
+ });
151
+ cli.parse(['node', 'bin', 'login', '--token', 'abc123'], { run: false });
152
+ await cli.runMatchedCommand();
153
+ expect(stdout.text).toBe('saved credentials\n');
154
+ expect(await readFile(join(tempDir, '.mycli/auth.json'), 'utf8')).toBe('{"token":"abc123"}');
155
+ }
156
+ finally {
157
+ process.chdir(originalCwd);
158
+ await rm(tempDir, { recursive: true, force: true });
159
+ }
160
+ });
161
+ });
162
+ describe('injected process context', () => {
163
+ test('command actions receive host cwd, env, and stdin defaults', async () => {
164
+ const stdout = createTestOutputStream();
165
+ const cli = gokeTestable('mycli', { stdout });
166
+ const originalCwd = process.cwd();
167
+ const originalEnv = process.env.GOKE_TEST_TOKEN;
168
+ const tempDir = await mkdtemp(join(tmpdir(), 'goke-process-'));
169
+ try {
170
+ process.chdir(tempDir);
171
+ process.env.GOKE_TEST_TOKEN = 'abc123';
172
+ cli
173
+ .command('context', 'Inspect process context')
174
+ .action((options, { console, process }) => {
175
+ console.log(JSON.stringify({
176
+ cwd: process.cwd,
177
+ stdin: process.stdin,
178
+ token: process.env.GOKE_TEST_TOKEN,
179
+ }));
180
+ });
181
+ cli.parse(['node', 'bin', 'context'], { run: false });
182
+ await cli.runMatchedCommand();
183
+ expect(stdout.text).toBe(`${JSON.stringify({ cwd: process.cwd(), stdin: '', token: 'abc123' })}\n`);
184
+ }
185
+ finally {
186
+ process.chdir(originalCwd);
187
+ if (originalEnv === undefined) {
188
+ delete process.env.GOKE_TEST_TOKEN;
189
+ }
190
+ else {
191
+ process.env.GOKE_TEST_TOKEN = originalEnv;
192
+ }
193
+ await rm(tempDir, { recursive: true, force: true });
194
+ }
195
+ });
196
+ test('custom injected env stays mutable inside command actions', async () => {
197
+ const stdout = createTestOutputStream();
198
+ const env = { TOKEN: 'before' };
199
+ const cli = gokeTestable('mycli', { env, stdout });
200
+ cli
201
+ .command('context', 'Mutate process env')
202
+ .action((options, { console, process }) => {
203
+ process.env.TOKEN = 'after';
204
+ console.log(process.env.TOKEN);
205
+ });
206
+ cli.parse(['node', 'bin', 'context'], { run: false });
207
+ await cli.runMatchedCommand();
208
+ expect(stdout.text).toBe('after\n');
209
+ expect(env.TOKEN).toBe('after');
210
+ });
211
+ });
132
212
  test('double dashes', () => {
133
213
  const cli = goke();
134
214
  const { args, options } = cli.parse([
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Tests for injected execution context, clone isolation, and the JustBash bridge.
3
+ */
4
+ export {};
5
+ //# sourceMappingURL=just-bash.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"just-bash.test.d.ts","sourceRoot":"","sources":["../../src/__test__/just-bash.test.ts"],"names":[],"mappings":"AAAA;;GAEG"}