goke 6.3.0 → 6.3.2
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 +13 -1
- package/dist/__test__/index.test.js +52 -0
- package/dist/goke.d.ts +8 -1
- package/dist/goke.d.ts.map +1 -1
- package/dist/goke.js +35 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/src/__test__/index.test.ts +72 -0
- package/src/goke.ts +35 -2
- package/src/index.ts +1 -1
package/README.md
CHANGED
|
@@ -525,7 +525,9 @@ When users run `--help`, deprecated options won't appear, but `--old-port 3000`
|
|
|
525
525
|
|
|
526
526
|
When using brackets in command name, angled brackets indicate required command arguments, while square brackets indicate optional arguments.
|
|
527
527
|
|
|
528
|
-
When using brackets in option name, angled brackets indicate that a string / number value is required, while square brackets indicate that the value
|
|
528
|
+
When using brackets in option name, angled brackets indicate that a string / number value is required, while square brackets indicate that the value is optional.
|
|
529
|
+
|
|
530
|
+
**Optionality is determined solely by bracket syntax, not by the schema.** `[square brackets]` makes an option optional regardless of whether the schema is `z.string()` or `z.string().optional()`. The schema's `.optional()` is never consulted for this — it only affects type coercion. This means `z.string()` with `[--name]` is treated as optional: if the flag is omitted, `options.name` is `undefined` even though the schema has no `.optional()`.
|
|
529
531
|
|
|
530
532
|
### Negated Options
|
|
531
533
|
|
|
@@ -665,6 +667,16 @@ cli
|
|
|
665
667
|
})
|
|
666
668
|
```
|
|
667
669
|
|
|
670
|
+
### Open in Browser
|
|
671
|
+
|
|
672
|
+
`openInBrowser` opens a URL in the default browser. In non-TTY environments (CI, piped output, agents), it prints the URL to stdout instead.
|
|
673
|
+
|
|
674
|
+
```ts
|
|
675
|
+
import { openInBrowser } from 'goke'
|
|
676
|
+
|
|
677
|
+
openInBrowser('https://example.com/dashboard')
|
|
678
|
+
```
|
|
679
|
+
|
|
668
680
|
## References
|
|
669
681
|
|
|
670
682
|
### CLI Instance
|
|
@@ -426,6 +426,35 @@ describe('regression: oracle-found issues', () => {
|
|
|
426
426
|
const { options } = cli.parse('node bin --tag foo --tag bar'.split(' '));
|
|
427
427
|
expect(options.tag).toEqual(['foo', 'bar']);
|
|
428
428
|
});
|
|
429
|
+
test('repeated optional value option without schema produces array', () => {
|
|
430
|
+
const cli = goke();
|
|
431
|
+
cli.option('--tag [tag]', 'Tags');
|
|
432
|
+
const { options } = cli.parse('node bin --tag foo --tag bar'.split(' '));
|
|
433
|
+
expect(options.tag).toEqual(['foo', 'bar']);
|
|
434
|
+
});
|
|
435
|
+
test('repeated alias option without schema produces array', () => {
|
|
436
|
+
const cli = goke();
|
|
437
|
+
cli.option('-t, --tag <tag>', 'Tags');
|
|
438
|
+
const { options } = cli.parse('node bin -t foo -t bar -t baz'.split(' '));
|
|
439
|
+
expect(options.tag).toEqual(['foo', 'bar', 'baz']);
|
|
440
|
+
expect(options.t).toEqual(['foo', 'bar', 'baz']);
|
|
441
|
+
});
|
|
442
|
+
test('repeated option without schema on subcommand produces array', () => {
|
|
443
|
+
const cli = goke();
|
|
444
|
+
let result = {};
|
|
445
|
+
cli
|
|
446
|
+
.command('build', 'Build')
|
|
447
|
+
.option('--exclude <path>', 'Paths to exclude')
|
|
448
|
+
.action((options) => { result = options; });
|
|
449
|
+
cli.parse('node bin build --exclude node_modules --exclude dist --exclude .git'.split(' '), { run: true });
|
|
450
|
+
expect(result.exclude).toEqual(['node_modules', 'dist', '.git']);
|
|
451
|
+
});
|
|
452
|
+
test('single value without schema stays as string (not wrapped in array)', () => {
|
|
453
|
+
const cli = goke();
|
|
454
|
+
cli.option('--tag <tag>', 'Tags');
|
|
455
|
+
const { options } = cli.parse('node bin --tag foo'.split(' '));
|
|
456
|
+
expect(options.tag).toBe('foo');
|
|
457
|
+
});
|
|
429
458
|
test('const null coercion works', () => {
|
|
430
459
|
expect(coerceBySchema('', { const: null }, 'val')).toBe(null);
|
|
431
460
|
});
|
|
@@ -1407,6 +1436,29 @@ describe('schema description and default extraction', () => {
|
|
|
1407
1436
|
expect(stdout.text).not.toContain('--legacy');
|
|
1408
1437
|
expect(stdout.text).not.toContain('Deprecated global');
|
|
1409
1438
|
});
|
|
1439
|
+
test('hidden commands are not shown in help output', () => {
|
|
1440
|
+
const stdout = createTestOutputStream();
|
|
1441
|
+
const cli = goke('mycli', { stdout });
|
|
1442
|
+
cli.command('visible', 'A visible command');
|
|
1443
|
+
cli.command('secret', 'A hidden command').hidden();
|
|
1444
|
+
cli.help();
|
|
1445
|
+
cli.parse(['node', 'bin', '--help'], { run: false });
|
|
1446
|
+
expect(stdout.text).toContain('visible');
|
|
1447
|
+
expect(stdout.text).toContain('A visible command');
|
|
1448
|
+
expect(stdout.text).not.toContain('secret');
|
|
1449
|
+
expect(stdout.text).not.toContain('A hidden command');
|
|
1450
|
+
});
|
|
1451
|
+
test('hidden command still parses and runs', () => {
|
|
1452
|
+
const cli = gokeTestable('mycli');
|
|
1453
|
+
let result = {};
|
|
1454
|
+
cli
|
|
1455
|
+
.command('secret', 'A hidden command')
|
|
1456
|
+
.hidden()
|
|
1457
|
+
.option('--value <v>', z.string().describe('some value'))
|
|
1458
|
+
.action((options) => { result = options; });
|
|
1459
|
+
cli.parse(['node', 'bin', 'secret', '--value', 'hello']);
|
|
1460
|
+
expect(result.value).toBe('hello');
|
|
1461
|
+
});
|
|
1410
1462
|
});
|
|
1411
1463
|
describe('helpText()', () => {
|
|
1412
1464
|
test('returns help string without printing', () => {
|
package/dist/goke.d.ts
CHANGED
|
@@ -101,6 +101,7 @@ declare class Command {
|
|
|
101
101
|
examples: CommandExample[];
|
|
102
102
|
helpCallback?: HelpCallback;
|
|
103
103
|
globalCommand?: GlobalCommand;
|
|
104
|
+
_hidden?: boolean;
|
|
104
105
|
constructor(rawName: string, description: string, config: CommandConfig | undefined, cli: Goke<any>);
|
|
105
106
|
usage(text: string): this;
|
|
106
107
|
allowUnknownOptions(): this;
|
|
@@ -128,6 +129,7 @@ declare class Command {
|
|
|
128
129
|
};
|
|
129
130
|
option(rawName: string, descriptionOrSchema?: string | StandardJSONSchemaV1): this;
|
|
130
131
|
alias(name: string): this;
|
|
132
|
+
hidden(): this;
|
|
131
133
|
action(callback: (...args: any[]) => any): this;
|
|
132
134
|
isMatched(args: string[]): {
|
|
133
135
|
matched: boolean;
|
|
@@ -349,7 +351,12 @@ declare class Goke<Opts extends Record<string, any> = {}> extends EventEmitter {
|
|
|
349
351
|
private mri;
|
|
350
352
|
runMatchedCommand(): any;
|
|
351
353
|
}
|
|
354
|
+
/**
|
|
355
|
+
* Open a URL in the default browser.
|
|
356
|
+
* In non-TTY environments (CI, piped output, agents), prints the URL to stdout instead.
|
|
357
|
+
*/
|
|
358
|
+
declare function openInBrowser(url: string): void;
|
|
352
359
|
export type { GokeOutputStream, GokeConsole, GokeOptions };
|
|
353
|
-
export { createConsole, Command };
|
|
360
|
+
export { createConsole, Command, openInBrowser };
|
|
354
361
|
export default Goke;
|
|
355
362
|
//# sourceMappingURL=goke.d.ts.map
|
package/dist/goke.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"goke.d.ts","sourceRoot":"","sources":["../src/goke.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"goke.d.ts","sourceRoot":"","sources":["../src/goke.ts"],"names":[],"mappings":"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"}
|
package/dist/goke.js
CHANGED
|
@@ -255,6 +255,7 @@ class Command {
|
|
|
255
255
|
examples;
|
|
256
256
|
helpCallback;
|
|
257
257
|
globalCommand;
|
|
258
|
+
_hidden;
|
|
258
259
|
constructor(rawName, description, config = {}, cli) {
|
|
259
260
|
this.rawName = rawName;
|
|
260
261
|
this.description = description;
|
|
@@ -296,6 +297,10 @@ class Command {
|
|
|
296
297
|
this.aliasNames.push(name);
|
|
297
298
|
return this;
|
|
298
299
|
}
|
|
300
|
+
hidden() {
|
|
301
|
+
this._hidden = true;
|
|
302
|
+
return this;
|
|
303
|
+
}
|
|
299
304
|
action(callback) {
|
|
300
305
|
this.commandAction = callback;
|
|
301
306
|
return this;
|
|
@@ -353,7 +358,7 @@ class Command {
|
|
|
353
358
|
const showCommands = (this.isGlobalCommand || this.isDefaultCommand) && commands.length > 0;
|
|
354
359
|
const terminalWidth = Math.max(this.cli.columns, 40);
|
|
355
360
|
if (showCommands) {
|
|
356
|
-
const commandRows = commands.map((command) => {
|
|
361
|
+
const commandRows = commands.filter((command) => !command._hidden).map((command) => {
|
|
357
362
|
const displayName = command.rawName.trim() === '' ? name : command.rawName;
|
|
358
363
|
// Hide deprecated options from subcommand help output
|
|
359
364
|
const displayOptions = command.isDefaultCommand ? [] : command.options.filter((o) => !o.deprecated);
|
|
@@ -1096,5 +1101,33 @@ class Goke extends EventEmitter {
|
|
|
1096
1101
|
return result;
|
|
1097
1102
|
}
|
|
1098
1103
|
}
|
|
1099
|
-
|
|
1104
|
+
// ─── openInBrowser ───
|
|
1105
|
+
/**
|
|
1106
|
+
* Open a URL in the default browser.
|
|
1107
|
+
* In non-TTY environments (CI, piped output, agents), prints the URL to stdout instead.
|
|
1108
|
+
*/
|
|
1109
|
+
function openInBrowser(url) {
|
|
1110
|
+
if (!process.stdout.isTTY) {
|
|
1111
|
+
console.error(url);
|
|
1112
|
+
return;
|
|
1113
|
+
}
|
|
1114
|
+
const { execSync } = require('child_process');
|
|
1115
|
+
const platform = process.platform;
|
|
1116
|
+
try {
|
|
1117
|
+
if (platform === 'darwin') {
|
|
1118
|
+
execSync(`open ${JSON.stringify(url)}`, { stdio: 'ignore' });
|
|
1119
|
+
}
|
|
1120
|
+
else if (platform === 'win32') {
|
|
1121
|
+
execSync(`start "" ${JSON.stringify(url)}`, { stdio: 'ignore' });
|
|
1122
|
+
}
|
|
1123
|
+
else {
|
|
1124
|
+
execSync(`xdg-open ${JSON.stringify(url)}`, { stdio: 'ignore' });
|
|
1125
|
+
}
|
|
1126
|
+
}
|
|
1127
|
+
catch {
|
|
1128
|
+
// fallback: print the URL if open fails
|
|
1129
|
+
console.error(url);
|
|
1130
|
+
}
|
|
1131
|
+
}
|
|
1132
|
+
export { createConsole, Command, openInBrowser };
|
|
1100
1133
|
export default Goke;
|
package/dist/index.d.ts
CHANGED
|
@@ -8,7 +8,7 @@ import { Command } from "./goke.js";
|
|
|
8
8
|
declare const goke: (name?: string, options?: GokeOptions) => Goke<{}>;
|
|
9
9
|
export default goke;
|
|
10
10
|
export { goke, Goke, Command };
|
|
11
|
-
export { createConsole } from "./goke.js";
|
|
11
|
+
export { createConsole, openInBrowser } from "./goke.js";
|
|
12
12
|
export type { GokeOutputStream, GokeConsole, GokeOptions } from "./goke.js";
|
|
13
13
|
export type { StandardTypedV1, StandardJSONSchemaV1, JsonSchema } from "./coerce.js";
|
|
14
14
|
export { GokeError, coerceBySchema, extractJsonSchema, wrapJsonSchema, isStandardSchema, extractSchemaMetadata } from "./coerce.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAA;AAC5B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AAC5C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAEnC;;;GAGG;AACH,QAAA,MAAM,IAAI,GAAI,aAAS,EAAE,UAAU,WAAW,aAA4B,CAAA;AAE1E,eAAe,IAAI,CAAA;AACnB,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,CAAA;AAC9B,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAA;AAC5B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AAC5C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAEnC;;;GAGG;AACH,QAAA,MAAM,IAAI,GAAI,aAAS,EAAE,UAAU,WAAW,aAA4B,CAAA;AAE1E,eAAe,IAAI,CAAA;AACnB,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,CAAA;AAC9B,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,WAAW,CAAA;AACxD,YAAY,EAAE,gBAAgB,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AAC3E,YAAY,EAAE,eAAe,EAAE,oBAAoB,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AACpF,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,iBAAiB,EAAE,cAAc,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -7,5 +7,5 @@ import { Command } from "./goke.js";
|
|
|
7
7
|
const goke = (name = '', options) => new Goke(name, options);
|
|
8
8
|
export default goke;
|
|
9
9
|
export { goke, Goke, Command };
|
|
10
|
-
export { createConsole } from "./goke.js";
|
|
10
|
+
export { createConsole, openInBrowser } from "./goke.js";
|
|
11
11
|
export { GokeError, coerceBySchema, extractJsonSchema, wrapJsonSchema, isStandardSchema, extractSchemaMetadata } from "./coerce.js";
|
package/package.json
CHANGED
|
@@ -551,6 +551,47 @@ describe('regression: oracle-found issues', () => {
|
|
|
551
551
|
expect(options.tag).toEqual(['foo', 'bar'])
|
|
552
552
|
})
|
|
553
553
|
|
|
554
|
+
test('repeated optional value option without schema produces array', () => {
|
|
555
|
+
const cli = goke()
|
|
556
|
+
|
|
557
|
+
cli.option('--tag [tag]', 'Tags')
|
|
558
|
+
|
|
559
|
+
const { options } = cli.parse('node bin --tag foo --tag bar'.split(' '))
|
|
560
|
+
expect(options.tag).toEqual(['foo', 'bar'])
|
|
561
|
+
})
|
|
562
|
+
|
|
563
|
+
test('repeated alias option without schema produces array', () => {
|
|
564
|
+
const cli = goke()
|
|
565
|
+
|
|
566
|
+
cli.option('-t, --tag <tag>', 'Tags')
|
|
567
|
+
|
|
568
|
+
const { options } = cli.parse('node bin -t foo -t bar -t baz'.split(' '))
|
|
569
|
+
expect(options.tag).toEqual(['foo', 'bar', 'baz'])
|
|
570
|
+
expect(options.t).toEqual(['foo', 'bar', 'baz'])
|
|
571
|
+
})
|
|
572
|
+
|
|
573
|
+
test('repeated option without schema on subcommand produces array', () => {
|
|
574
|
+
const cli = goke()
|
|
575
|
+
let result: any = {}
|
|
576
|
+
|
|
577
|
+
cli
|
|
578
|
+
.command('build', 'Build')
|
|
579
|
+
.option('--exclude <path>', 'Paths to exclude')
|
|
580
|
+
.action((options) => { result = options })
|
|
581
|
+
|
|
582
|
+
cli.parse('node bin build --exclude node_modules --exclude dist --exclude .git'.split(' '), { run: true })
|
|
583
|
+
expect(result.exclude).toEqual(['node_modules', 'dist', '.git'])
|
|
584
|
+
})
|
|
585
|
+
|
|
586
|
+
test('single value without schema stays as string (not wrapped in array)', () => {
|
|
587
|
+
const cli = goke()
|
|
588
|
+
|
|
589
|
+
cli.option('--tag <tag>', 'Tags')
|
|
590
|
+
|
|
591
|
+
const { options } = cli.parse('node bin --tag foo'.split(' '))
|
|
592
|
+
expect(options.tag).toBe('foo')
|
|
593
|
+
})
|
|
594
|
+
|
|
554
595
|
test('const null coercion works', () => {
|
|
555
596
|
expect(coerceBySchema('', { const: null }, 'val')).toBe(null)
|
|
556
597
|
})
|
|
@@ -1795,6 +1836,37 @@ describe('schema description and default extraction', () => {
|
|
|
1795
1836
|
expect(stdout.text).not.toContain('--legacy')
|
|
1796
1837
|
expect(stdout.text).not.toContain('Deprecated global')
|
|
1797
1838
|
})
|
|
1839
|
+
|
|
1840
|
+
test('hidden commands are not shown in help output', () => {
|
|
1841
|
+
const stdout = createTestOutputStream()
|
|
1842
|
+
const cli = goke('mycli', { stdout })
|
|
1843
|
+
|
|
1844
|
+
cli.command('visible', 'A visible command')
|
|
1845
|
+
cli.command('secret', 'A hidden command').hidden()
|
|
1846
|
+
|
|
1847
|
+
cli.help()
|
|
1848
|
+
cli.parse(['node', 'bin', '--help'], { run: false })
|
|
1849
|
+
|
|
1850
|
+
expect(stdout.text).toContain('visible')
|
|
1851
|
+
expect(stdout.text).toContain('A visible command')
|
|
1852
|
+
expect(stdout.text).not.toContain('secret')
|
|
1853
|
+
expect(stdout.text).not.toContain('A hidden command')
|
|
1854
|
+
})
|
|
1855
|
+
|
|
1856
|
+
test('hidden command still parses and runs', () => {
|
|
1857
|
+
const cli = gokeTestable('mycli')
|
|
1858
|
+
|
|
1859
|
+
let result: any = {}
|
|
1860
|
+
cli
|
|
1861
|
+
.command('secret', 'A hidden command')
|
|
1862
|
+
.hidden()
|
|
1863
|
+
.option('--value <v>', z.string().describe('some value'))
|
|
1864
|
+
.action((options) => { result = options })
|
|
1865
|
+
|
|
1866
|
+
cli.parse(['node', 'bin', 'secret', '--value', 'hello'])
|
|
1867
|
+
|
|
1868
|
+
expect(result.value).toBe('hello')
|
|
1869
|
+
})
|
|
1798
1870
|
})
|
|
1799
1871
|
|
|
1800
1872
|
describe('helpText()', () => {
|
package/src/goke.ts
CHANGED
|
@@ -373,6 +373,7 @@ class Command {
|
|
|
373
373
|
examples: CommandExample[]
|
|
374
374
|
helpCallback?: HelpCallback
|
|
375
375
|
globalCommand?: GlobalCommand
|
|
376
|
+
_hidden?: boolean
|
|
376
377
|
|
|
377
378
|
constructor(
|
|
378
379
|
public rawName: string,
|
|
@@ -445,6 +446,11 @@ class Command {
|
|
|
445
446
|
return this
|
|
446
447
|
}
|
|
447
448
|
|
|
449
|
+
hidden() {
|
|
450
|
+
this._hidden = true
|
|
451
|
+
return this
|
|
452
|
+
}
|
|
453
|
+
|
|
448
454
|
action(callback: (...args: any[]) => any) {
|
|
449
455
|
this.commandAction = callback
|
|
450
456
|
return this
|
|
@@ -520,7 +526,7 @@ class Command {
|
|
|
520
526
|
const terminalWidth = Math.max(this.cli.columns, 40)
|
|
521
527
|
|
|
522
528
|
if (showCommands) {
|
|
523
|
-
const commandRows = commands.map((command) => {
|
|
529
|
+
const commandRows = commands.filter((command) => !command._hidden).map((command) => {
|
|
524
530
|
const displayName = command.rawName.trim() === '' ? name : command.rawName
|
|
525
531
|
// Hide deprecated options from subcommand help output
|
|
526
532
|
const displayOptions = command.isDefaultCommand ? [] : command.options.filter((o) => !o.deprecated)
|
|
@@ -1440,8 +1446,35 @@ class Goke<Opts extends Record<string, any> = {}> extends EventEmitter {
|
|
|
1440
1446
|
}
|
|
1441
1447
|
}
|
|
1442
1448
|
|
|
1449
|
+
// ─── openInBrowser ───
|
|
1450
|
+
|
|
1451
|
+
/**
|
|
1452
|
+
* Open a URL in the default browser.
|
|
1453
|
+
* In non-TTY environments (CI, piped output, agents), prints the URL to stdout instead.
|
|
1454
|
+
*/
|
|
1455
|
+
function openInBrowser(url: string): void {
|
|
1456
|
+
if (!process.stdout.isTTY) {
|
|
1457
|
+
console.error(url)
|
|
1458
|
+
return
|
|
1459
|
+
}
|
|
1460
|
+
const { execSync } = require('child_process') as typeof import('child_process')
|
|
1461
|
+
const platform = process.platform
|
|
1462
|
+
try {
|
|
1463
|
+
if (platform === 'darwin') {
|
|
1464
|
+
execSync(`open ${JSON.stringify(url)}`, { stdio: 'ignore' })
|
|
1465
|
+
} else if (platform === 'win32') {
|
|
1466
|
+
execSync(`start "" ${JSON.stringify(url)}`, { stdio: 'ignore' })
|
|
1467
|
+
} else {
|
|
1468
|
+
execSync(`xdg-open ${JSON.stringify(url)}`, { stdio: 'ignore' })
|
|
1469
|
+
}
|
|
1470
|
+
} catch {
|
|
1471
|
+
// fallback: print the URL if open fails
|
|
1472
|
+
console.error(url)
|
|
1473
|
+
}
|
|
1474
|
+
}
|
|
1475
|
+
|
|
1443
1476
|
// ─── Exports ───
|
|
1444
1477
|
|
|
1445
1478
|
export type { GokeOutputStream, GokeConsole, GokeOptions }
|
|
1446
|
-
export { createConsole, Command }
|
|
1479
|
+
export { createConsole, Command, openInBrowser }
|
|
1447
1480
|
export default Goke
|
package/src/index.ts
CHANGED
|
@@ -10,7 +10,7 @@ const goke = (name = '', options?: GokeOptions) => new Goke(name, options)
|
|
|
10
10
|
|
|
11
11
|
export default goke
|
|
12
12
|
export { goke, Goke, Command }
|
|
13
|
-
export { createConsole } from "./goke.js"
|
|
13
|
+
export { createConsole, openInBrowser } from "./goke.js"
|
|
14
14
|
export type { GokeOutputStream, GokeConsole, GokeOptions } from "./goke.js"
|
|
15
15
|
export type { StandardTypedV1, StandardJSONSchemaV1, JsonSchema } from "./coerce.js"
|
|
16
16
|
export { GokeError, coerceBySchema, extractJsonSchema, wrapJsonSchema, isStandardSchema, extractSchemaMetadata } from "./coerce.js"
|