goke 6.5.0 → 6.5.1
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 +137 -0
- package/dist/goke.js +1 -1
- package/dist/picocolors.d.ts +55 -0
- package/dist/picocolors.d.ts.map +1 -0
- package/dist/picocolors.js +78 -0
- package/package.json +2 -4
- package/src/goke.ts +1 -1
- package/src/picocolors.ts +140 -0
package/README.md
CHANGED
|
@@ -25,6 +25,14 @@
|
|
|
25
25
|
npm install goke
|
|
26
26
|
```
|
|
27
27
|
|
|
28
|
+
## Install skill for AI agents
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
npx -y skills add remorses/goke
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
This installs the repository skill for AI coding agents. In this repo the shipped skill lives at `skills/goke/SKILL.md`.
|
|
35
|
+
|
|
28
36
|
## Usage
|
|
29
37
|
|
|
30
38
|
### Simple Parsing
|
|
@@ -390,6 +398,22 @@ cli
|
|
|
390
398
|
|
|
391
399
|
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
400
|
|
|
401
|
+
### Path handling
|
|
402
|
+
|
|
403
|
+
Use relative paths with injected `fs` for routine CLI storage paths. When a helper needs to resolve from the current directory, pass injected `process.cwd` into that helper and resolve from there.
|
|
404
|
+
|
|
405
|
+
```ts
|
|
406
|
+
await fs.mkdir('.mycli', { recursive: true })
|
|
407
|
+
await fs.writeFile('.mycli/auth.json', json, 'utf8')
|
|
408
|
+
console.log('running from', process.cwd)
|
|
409
|
+
```
|
|
410
|
+
|
|
411
|
+
Why this works:
|
|
412
|
+
|
|
413
|
+
- In normal Node.js runs, relative paths resolve against the host cwd.
|
|
414
|
+
- In JustBash runs, the same relative paths resolve against the sandbox cwd.
|
|
415
|
+
- `process.cwd` mirrors that runtime-specific cwd in both environments.
|
|
416
|
+
|
|
393
417
|
`goke` also exports the runtime types, so helper functions can use dependency injection without reaching for globals:
|
|
394
418
|
|
|
395
419
|
```ts
|
|
@@ -810,6 +834,78 @@ await bash.exec('parent child commandwithspaces --name Tommy')
|
|
|
810
834
|
|
|
811
835
|
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
836
|
|
|
837
|
+
### Test with real JustBash
|
|
838
|
+
|
|
839
|
+
When a command reads or writes files, test it through real `just-bash` using the existing app CLI. Do not define the CLI inside the test body.
|
|
840
|
+
|
|
841
|
+
```ts
|
|
842
|
+
import { describe, expect, test } from 'vitest'
|
|
843
|
+
import { Bash, InMemoryFs } from 'just-bash'
|
|
844
|
+
import { cli } from '../src/cli'
|
|
845
|
+
|
|
846
|
+
describe('login command', () => {
|
|
847
|
+
test('writes auth state through the sandbox fs', async () => {
|
|
848
|
+
const virtualFs = new InMemoryFs()
|
|
849
|
+
await virtualFs.mkdir('/project', { recursive: true })
|
|
850
|
+
|
|
851
|
+
const bash = new Bash({
|
|
852
|
+
fs: virtualFs,
|
|
853
|
+
cwd: '/project',
|
|
854
|
+
customCommands: [await cli.createJustBashCommand()],
|
|
855
|
+
})
|
|
856
|
+
|
|
857
|
+
const result = await bash.exec('parent login --token Tommy')
|
|
858
|
+
|
|
859
|
+
expect(result.stdout).toBe('saved credentials\n')
|
|
860
|
+
expect(await virtualFs.readFile('/project/.mycli/auth.json', 'utf8')).toBe(
|
|
861
|
+
'{"token":"Tommy","cwd":"/project"}',
|
|
862
|
+
)
|
|
863
|
+
})
|
|
864
|
+
})
|
|
865
|
+
```
|
|
866
|
+
|
|
867
|
+
This is the recommended compatibility test whenever a CLI touches storage: run the same CLI once in normal tests and once through real `just-bash`.
|
|
868
|
+
|
|
869
|
+
### Exposing your CLI as a skill
|
|
870
|
+
|
|
871
|
+
If you build a CLI with goke, keep the skill minimal and point agents to the CLI help output. Put detailed usage in the CLI code and README, not in a duplicated skill file.
|
|
872
|
+
|
|
873
|
+
````markdown
|
|
874
|
+
<!-- skills/acme/SKILL.md -->
|
|
875
|
+
---
|
|
876
|
+
name: acme
|
|
877
|
+
description: >
|
|
878
|
+
acme is a deployment CLI. Always run `acme --help` before using it
|
|
879
|
+
to discover available commands, options, and usage examples.
|
|
880
|
+
---
|
|
881
|
+
|
|
882
|
+
# acme
|
|
883
|
+
|
|
884
|
+
Always run `acme --help` before using this CLI.
|
|
885
|
+
For subcommand details: `acme <command> --help`
|
|
886
|
+
````
|
|
887
|
+
|
|
888
|
+
## Contributor Notes
|
|
889
|
+
|
|
890
|
+
### Rules
|
|
891
|
+
|
|
892
|
+
1. Use schema-based options for typed values.
|
|
893
|
+
2. Do not repeat defaults in `.describe(...)` when using `.default()`.
|
|
894
|
+
3. Do not manually type action callback arguments; let goke infer them.
|
|
895
|
+
4. Prefer injected `{ fs, console, process }` over global `console`, `process.exit`, or direct `node:fs/promises` imports.
|
|
896
|
+
5. Use implicit cwd with injected `fs` for CLI storage. When a helper needs current-cwd semantics, pass `process.cwd` from the injected context into that helper.
|
|
897
|
+
6. Define the CLI in app code and import that same CLI in tests; do not construct a separate CLI inside compatibility tests.
|
|
898
|
+
|
|
899
|
+
### Version
|
|
900
|
+
|
|
901
|
+
Import `package.json` and use its version field so the CLI stays in sync automatically:
|
|
902
|
+
|
|
903
|
+
```ts
|
|
904
|
+
import pkg from './package.json' with { type: 'json' }
|
|
905
|
+
|
|
906
|
+
cli.version(pkg.version)
|
|
907
|
+
```
|
|
908
|
+
|
|
813
909
|
## References
|
|
814
910
|
|
|
815
911
|
### CLI Instance
|
|
@@ -867,6 +963,26 @@ Register a middleware function that runs before the matched command action. Midd
|
|
|
867
963
|
|
|
868
964
|
Print the help message to stdout.
|
|
869
965
|
|
|
966
|
+
#### cli.clone(options?)
|
|
967
|
+
|
|
968
|
+
- Type: `(options?: GokeOptions) => Goke`
|
|
969
|
+
|
|
970
|
+
Create a deep copy of the CLI instance with all commands, options, middleware, and event listeners. Override any `GokeOptions` (stdout, stderr, cwd, env, fs, argv, columns, exit) in the clone without affecting the original. Primarily useful in tests to run multiple isolated parses from the same CLI definition:
|
|
971
|
+
|
|
972
|
+
```ts
|
|
973
|
+
const cli = goke('mycli')
|
|
974
|
+
cli.command('build', 'Build project').action((options, { console }) => {
|
|
975
|
+
console.log('building')
|
|
976
|
+
})
|
|
977
|
+
cli.help()
|
|
978
|
+
|
|
979
|
+
// In tests: override streams without touching the original CLI
|
|
980
|
+
const stdout = { write: vi.fn<(data: string) => void>() }
|
|
981
|
+
const isolated = cli.clone({ stdout })
|
|
982
|
+
isolated.parse(['node', 'mycli', 'build'])
|
|
983
|
+
expect(stdout.write).toHaveBeenCalledWith('building\n')
|
|
984
|
+
```
|
|
985
|
+
|
|
870
986
|
#### cli.helpText()
|
|
871
987
|
|
|
872
988
|
- Type: `() => string`
|
|
@@ -911,6 +1027,21 @@ Command callbacks receive positional args first, then parsed options, then an in
|
|
|
911
1027
|
|
|
912
1028
|
- Type: `() => Command`
|
|
913
1029
|
|
|
1030
|
+
#### command.hidden()
|
|
1031
|
+
|
|
1032
|
+
- Type: `() => Command`
|
|
1033
|
+
|
|
1034
|
+
Hide a command from the help output listing. The command still matches and runs when invoked directly — only the help display is suppressed. Useful for internal, deprecated, or experimental commands you don't want to advertise.
|
|
1035
|
+
|
|
1036
|
+
```ts
|
|
1037
|
+
cli
|
|
1038
|
+
.command('internal-reset', 'Reset internal state')
|
|
1039
|
+
.hidden()
|
|
1040
|
+
.action((options, { console }) => {
|
|
1041
|
+
console.log('reset done')
|
|
1042
|
+
})
|
|
1043
|
+
```
|
|
1044
|
+
|
|
914
1045
|
#### command.example(example)
|
|
915
1046
|
|
|
916
1047
|
- Type: `(example: CommandExample) => Command`
|
|
@@ -919,6 +1050,12 @@ Command callbacks receive positional args first, then parsed options, then an in
|
|
|
919
1050
|
|
|
920
1051
|
- Type: `(text: string) => Command`
|
|
921
1052
|
|
|
1053
|
+
#### command.helpText()
|
|
1054
|
+
|
|
1055
|
+
- Type: `() => string`
|
|
1056
|
+
|
|
1057
|
+
Return the formatted help string for this specific command without printing it. Useful for tests or embedding help text programmatically.
|
|
1058
|
+
|
|
922
1059
|
### Events
|
|
923
1060
|
|
|
924
1061
|
Listen to commands:
|
package/dist/goke.js
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* - createConsole: factory for console-like objects from output streams
|
|
10
10
|
* - Utility functions: string helpers, bracket parsing, dot-prop access
|
|
11
11
|
*/
|
|
12
|
-
import pc from 'picocolors';
|
|
12
|
+
import pc from './picocolors.js';
|
|
13
13
|
import mri from "./mri.js";
|
|
14
14
|
import { GokeError, coerceBySchema, extractJsonSchema, extractSchemaMetadata, isStandardSchema } from "./coerce.js";
|
|
15
15
|
import { createJustBashCommand as createJustBashCommandBridge } from './just-bash.js';
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vendored from picocolors by Alexey Raspopov (MIT license).
|
|
3
|
+
* Source: https://github.com/alexeyraspopov/picocolors/blob/main/picocolors.js
|
|
4
|
+
*/
|
|
5
|
+
type Formatter = (input: unknown) => string;
|
|
6
|
+
interface PicoColors {
|
|
7
|
+
isColorSupported: boolean;
|
|
8
|
+
reset: Formatter;
|
|
9
|
+
bold: Formatter;
|
|
10
|
+
dim: Formatter;
|
|
11
|
+
italic: Formatter;
|
|
12
|
+
underline: Formatter;
|
|
13
|
+
inverse: Formatter;
|
|
14
|
+
hidden: Formatter;
|
|
15
|
+
strikethrough: Formatter;
|
|
16
|
+
black: Formatter;
|
|
17
|
+
red: Formatter;
|
|
18
|
+
green: Formatter;
|
|
19
|
+
yellow: Formatter;
|
|
20
|
+
blue: Formatter;
|
|
21
|
+
magenta: Formatter;
|
|
22
|
+
cyan: Formatter;
|
|
23
|
+
white: Formatter;
|
|
24
|
+
gray: Formatter;
|
|
25
|
+
bgBlack: Formatter;
|
|
26
|
+
bgRed: Formatter;
|
|
27
|
+
bgGreen: Formatter;
|
|
28
|
+
bgYellow: Formatter;
|
|
29
|
+
bgBlue: Formatter;
|
|
30
|
+
bgMagenta: Formatter;
|
|
31
|
+
bgCyan: Formatter;
|
|
32
|
+
bgWhite: Formatter;
|
|
33
|
+
blackBright: Formatter;
|
|
34
|
+
redBright: Formatter;
|
|
35
|
+
greenBright: Formatter;
|
|
36
|
+
yellowBright: Formatter;
|
|
37
|
+
blueBright: Formatter;
|
|
38
|
+
magentaBright: Formatter;
|
|
39
|
+
cyanBright: Formatter;
|
|
40
|
+
whiteBright: Formatter;
|
|
41
|
+
bgBlackBright: Formatter;
|
|
42
|
+
bgRedBright: Formatter;
|
|
43
|
+
bgGreenBright: Formatter;
|
|
44
|
+
bgYellowBright: Formatter;
|
|
45
|
+
bgBlueBright: Formatter;
|
|
46
|
+
bgMagentaBright: Formatter;
|
|
47
|
+
bgCyanBright: Formatter;
|
|
48
|
+
bgWhiteBright: Formatter;
|
|
49
|
+
}
|
|
50
|
+
declare const createColors: (enabled?: boolean) => PicoColors;
|
|
51
|
+
declare const pc: PicoColors;
|
|
52
|
+
export { createColors };
|
|
53
|
+
export type { PicoColors };
|
|
54
|
+
export default pc;
|
|
55
|
+
//# sourceMappingURL=picocolors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"picocolors.d.ts","sourceRoot":"","sources":["../src/picocolors.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,KAAK,SAAS,GAAG,CAAC,KAAK,EAAE,OAAO,KAAK,MAAM,CAAA;AAE3C,UAAU,UAAU;IAClB,gBAAgB,EAAE,OAAO,CAAA;IACzB,KAAK,EAAE,SAAS,CAAA;IAChB,IAAI,EAAE,SAAS,CAAA;IACf,GAAG,EAAE,SAAS,CAAA;IACd,MAAM,EAAE,SAAS,CAAA;IACjB,SAAS,EAAE,SAAS,CAAA;IACpB,OAAO,EAAE,SAAS,CAAA;IAClB,MAAM,EAAE,SAAS,CAAA;IACjB,aAAa,EAAE,SAAS,CAAA;IACxB,KAAK,EAAE,SAAS,CAAA;IAChB,GAAG,EAAE,SAAS,CAAA;IACd,KAAK,EAAE,SAAS,CAAA;IAChB,MAAM,EAAE,SAAS,CAAA;IACjB,IAAI,EAAE,SAAS,CAAA;IACf,OAAO,EAAE,SAAS,CAAA;IAClB,IAAI,EAAE,SAAS,CAAA;IACf,KAAK,EAAE,SAAS,CAAA;IAChB,IAAI,EAAE,SAAS,CAAA;IACf,OAAO,EAAE,SAAS,CAAA;IAClB,KAAK,EAAE,SAAS,CAAA;IAChB,OAAO,EAAE,SAAS,CAAA;IAClB,QAAQ,EAAE,SAAS,CAAA;IACnB,MAAM,EAAE,SAAS,CAAA;IACjB,SAAS,EAAE,SAAS,CAAA;IACpB,MAAM,EAAE,SAAS,CAAA;IACjB,OAAO,EAAE,SAAS,CAAA;IAClB,WAAW,EAAE,SAAS,CAAA;IACtB,SAAS,EAAE,SAAS,CAAA;IACpB,WAAW,EAAE,SAAS,CAAA;IACtB,YAAY,EAAE,SAAS,CAAA;IACvB,UAAU,EAAE,SAAS,CAAA;IACrB,aAAa,EAAE,SAAS,CAAA;IACxB,UAAU,EAAE,SAAS,CAAA;IACrB,WAAW,EAAE,SAAS,CAAA;IACtB,aAAa,EAAE,SAAS,CAAA;IACxB,WAAW,EAAE,SAAS,CAAA;IACtB,aAAa,EAAE,SAAS,CAAA;IACxB,cAAc,EAAE,SAAS,CAAA;IACzB,YAAY,EAAE,SAAS,CAAA;IACvB,eAAe,EAAE,SAAS,CAAA;IAC1B,YAAY,EAAE,SAAS,CAAA;IACvB,aAAa,EAAE,SAAS,CAAA;CACzB;AAkCD,QAAA,MAAM,YAAY,GAAI,iBAA0B,KAAG,UA+ClD,CAAA;AAED,QAAA,MAAM,EAAE,YAAiB,CAAA;AAEzB,OAAO,EAAE,YAAY,EAAE,CAAA;AACvB,YAAY,EAAE,UAAU,EAAE,CAAA;AAC1B,eAAe,EAAE,CAAA"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vendored from picocolors by Alexey Raspopov (MIT license).
|
|
3
|
+
* Source: https://github.com/alexeyraspopov/picocolors/blob/main/picocolors.js
|
|
4
|
+
*/
|
|
5
|
+
import { process } from '#runtime';
|
|
6
|
+
const argv = process.argv || [];
|
|
7
|
+
const env = process.env || {};
|
|
8
|
+
const isColorSupported = !(!!env.NO_COLOR || argv.includes('--no-color'))
|
|
9
|
+
&& (!!env.FORCE_COLOR
|
|
10
|
+
|| argv.includes('--color')
|
|
11
|
+
|| process.platform === 'win32'
|
|
12
|
+
|| (process.stdout.isTTY && env.TERM !== 'dumb')
|
|
13
|
+
|| !!env.CI);
|
|
14
|
+
const replaceClose = (string, close, replace, index) => {
|
|
15
|
+
let result = '';
|
|
16
|
+
let cursor = 0;
|
|
17
|
+
do {
|
|
18
|
+
result += string.substring(cursor, index) + replace;
|
|
19
|
+
cursor = index + close.length;
|
|
20
|
+
index = string.indexOf(close, cursor);
|
|
21
|
+
} while (~index);
|
|
22
|
+
return result + string.substring(cursor);
|
|
23
|
+
};
|
|
24
|
+
const formatter = (open, close, replace = open) => (input) => {
|
|
25
|
+
const string = String(input);
|
|
26
|
+
const index = string.indexOf(close, open.length);
|
|
27
|
+
return ~index ? open + replaceClose(string, close, replace, index) + close : open + string + close;
|
|
28
|
+
};
|
|
29
|
+
const createColors = (enabled = isColorSupported) => {
|
|
30
|
+
const f = enabled ? formatter : () => String;
|
|
31
|
+
return {
|
|
32
|
+
isColorSupported: enabled,
|
|
33
|
+
reset: f('\x1b[0m', '\x1b[0m'),
|
|
34
|
+
bold: f('\x1b[1m', '\x1b[22m', '\x1b[22m\x1b[1m'),
|
|
35
|
+
dim: f('\x1b[2m', '\x1b[22m', '\x1b[22m\x1b[2m'),
|
|
36
|
+
italic: f('\x1b[3m', '\x1b[23m'),
|
|
37
|
+
underline: f('\x1b[4m', '\x1b[24m'),
|
|
38
|
+
inverse: f('\x1b[7m', '\x1b[27m'),
|
|
39
|
+
hidden: f('\x1b[8m', '\x1b[28m'),
|
|
40
|
+
strikethrough: f('\x1b[9m', '\x1b[29m'),
|
|
41
|
+
black: f('\x1b[30m', '\x1b[39m'),
|
|
42
|
+
red: f('\x1b[31m', '\x1b[39m'),
|
|
43
|
+
green: f('\x1b[32m', '\x1b[39m'),
|
|
44
|
+
yellow: f('\x1b[33m', '\x1b[39m'),
|
|
45
|
+
blue: f('\x1b[34m', '\x1b[39m'),
|
|
46
|
+
magenta: f('\x1b[35m', '\x1b[39m'),
|
|
47
|
+
cyan: f('\x1b[36m', '\x1b[39m'),
|
|
48
|
+
white: f('\x1b[37m', '\x1b[39m'),
|
|
49
|
+
gray: f('\x1b[90m', '\x1b[39m'),
|
|
50
|
+
bgBlack: f('\x1b[40m', '\x1b[49m'),
|
|
51
|
+
bgRed: f('\x1b[41m', '\x1b[49m'),
|
|
52
|
+
bgGreen: f('\x1b[42m', '\x1b[49m'),
|
|
53
|
+
bgYellow: f('\x1b[43m', '\x1b[49m'),
|
|
54
|
+
bgBlue: f('\x1b[44m', '\x1b[49m'),
|
|
55
|
+
bgMagenta: f('\x1b[45m', '\x1b[49m'),
|
|
56
|
+
bgCyan: f('\x1b[46m', '\x1b[49m'),
|
|
57
|
+
bgWhite: f('\x1b[47m', '\x1b[49m'),
|
|
58
|
+
blackBright: f('\x1b[90m', '\x1b[39m'),
|
|
59
|
+
redBright: f('\x1b[91m', '\x1b[39m'),
|
|
60
|
+
greenBright: f('\x1b[92m', '\x1b[39m'),
|
|
61
|
+
yellowBright: f('\x1b[93m', '\x1b[39m'),
|
|
62
|
+
blueBright: f('\x1b[94m', '\x1b[39m'),
|
|
63
|
+
magentaBright: f('\x1b[95m', '\x1b[39m'),
|
|
64
|
+
cyanBright: f('\x1b[96m', '\x1b[39m'),
|
|
65
|
+
whiteBright: f('\x1b[97m', '\x1b[39m'),
|
|
66
|
+
bgBlackBright: f('\x1b[100m', '\x1b[49m'),
|
|
67
|
+
bgRedBright: f('\x1b[101m', '\x1b[49m'),
|
|
68
|
+
bgGreenBright: f('\x1b[102m', '\x1b[49m'),
|
|
69
|
+
bgYellowBright: f('\x1b[103m', '\x1b[49m'),
|
|
70
|
+
bgBlueBright: f('\x1b[104m', '\x1b[49m'),
|
|
71
|
+
bgMagentaBright: f('\x1b[105m', '\x1b[49m'),
|
|
72
|
+
bgCyanBright: f('\x1b[106m', '\x1b[49m'),
|
|
73
|
+
bgWhiteBright: f('\x1b[107m', '\x1b[49m'),
|
|
74
|
+
};
|
|
75
|
+
};
|
|
76
|
+
const pc = createColors();
|
|
77
|
+
export { createColors };
|
|
78
|
+
export default pc;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "goke",
|
|
3
|
-
"version": "6.5.
|
|
3
|
+
"version": "6.5.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Simple yet powerful framework for building command-line apps. Inspired by cac.",
|
|
6
6
|
"repository": {
|
|
@@ -48,9 +48,7 @@
|
|
|
48
48
|
"dist",
|
|
49
49
|
"src"
|
|
50
50
|
],
|
|
51
|
-
"dependencies": {
|
|
52
|
-
"picocolors": "^1.1.1"
|
|
53
|
-
},
|
|
51
|
+
"dependencies": {},
|
|
54
52
|
"author": "remorses, egoist <0x142857@gmail.com>",
|
|
55
53
|
"license": "MIT",
|
|
56
54
|
"devDependencies": {
|
package/src/goke.ts
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* - Utility functions: string helpers, bracket parsing, dot-prop access
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
-
import pc from 'picocolors'
|
|
13
|
+
import pc from './picocolors.js'
|
|
14
14
|
import mri from "./mri.js"
|
|
15
15
|
import { GokeError, coerceBySchema, extractJsonSchema, extractSchemaMetadata, isStandardSchema } from "./coerce.js"
|
|
16
16
|
import type { StandardJSONSchemaV1 } from "./coerce.js"
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vendored from picocolors by Alexey Raspopov (MIT license).
|
|
3
|
+
* Source: https://github.com/alexeyraspopov/picocolors/blob/main/picocolors.js
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { process } from '#runtime'
|
|
7
|
+
|
|
8
|
+
type Formatter = (input: unknown) => string
|
|
9
|
+
|
|
10
|
+
interface PicoColors {
|
|
11
|
+
isColorSupported: boolean
|
|
12
|
+
reset: Formatter
|
|
13
|
+
bold: Formatter
|
|
14
|
+
dim: Formatter
|
|
15
|
+
italic: Formatter
|
|
16
|
+
underline: Formatter
|
|
17
|
+
inverse: Formatter
|
|
18
|
+
hidden: Formatter
|
|
19
|
+
strikethrough: Formatter
|
|
20
|
+
black: Formatter
|
|
21
|
+
red: Formatter
|
|
22
|
+
green: Formatter
|
|
23
|
+
yellow: Formatter
|
|
24
|
+
blue: Formatter
|
|
25
|
+
magenta: Formatter
|
|
26
|
+
cyan: Formatter
|
|
27
|
+
white: Formatter
|
|
28
|
+
gray: Formatter
|
|
29
|
+
bgBlack: Formatter
|
|
30
|
+
bgRed: Formatter
|
|
31
|
+
bgGreen: Formatter
|
|
32
|
+
bgYellow: Formatter
|
|
33
|
+
bgBlue: Formatter
|
|
34
|
+
bgMagenta: Formatter
|
|
35
|
+
bgCyan: Formatter
|
|
36
|
+
bgWhite: Formatter
|
|
37
|
+
blackBright: Formatter
|
|
38
|
+
redBright: Formatter
|
|
39
|
+
greenBright: Formatter
|
|
40
|
+
yellowBright: Formatter
|
|
41
|
+
blueBright: Formatter
|
|
42
|
+
magentaBright: Formatter
|
|
43
|
+
cyanBright: Formatter
|
|
44
|
+
whiteBright: Formatter
|
|
45
|
+
bgBlackBright: Formatter
|
|
46
|
+
bgRedBright: Formatter
|
|
47
|
+
bgGreenBright: Formatter
|
|
48
|
+
bgYellowBright: Formatter
|
|
49
|
+
bgBlueBright: Formatter
|
|
50
|
+
bgMagentaBright: Formatter
|
|
51
|
+
bgCyanBright: Formatter
|
|
52
|
+
bgWhiteBright: Formatter
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const argv = process.argv || []
|
|
56
|
+
const env = process.env || {}
|
|
57
|
+
const isColorSupported =
|
|
58
|
+
!(!!env.NO_COLOR || argv.includes('--no-color'))
|
|
59
|
+
&& (
|
|
60
|
+
!!env.FORCE_COLOR
|
|
61
|
+
|| argv.includes('--color')
|
|
62
|
+
|| process.platform === 'win32'
|
|
63
|
+
|| (process.stdout.isTTY && env.TERM !== 'dumb')
|
|
64
|
+
|| !!env.CI
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
const replaceClose = (string: string, close: string, replace: string, index: number) => {
|
|
68
|
+
let result = ''
|
|
69
|
+
let cursor = 0
|
|
70
|
+
|
|
71
|
+
do {
|
|
72
|
+
result += string.substring(cursor, index) + replace
|
|
73
|
+
cursor = index + close.length
|
|
74
|
+
index = string.indexOf(close, cursor)
|
|
75
|
+
} while (~index)
|
|
76
|
+
|
|
77
|
+
return result + string.substring(cursor)
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const formatter = (open: string, close: string, replace = open): Formatter =>
|
|
81
|
+
(input) => {
|
|
82
|
+
const string = String(input)
|
|
83
|
+
const index = string.indexOf(close, open.length)
|
|
84
|
+
return ~index ? open + replaceClose(string, close, replace, index) + close : open + string + close
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const createColors = (enabled = isColorSupported): PicoColors => {
|
|
88
|
+
const f = enabled ? formatter : () => String
|
|
89
|
+
|
|
90
|
+
return {
|
|
91
|
+
isColorSupported: enabled,
|
|
92
|
+
reset: f('\x1b[0m', '\x1b[0m'),
|
|
93
|
+
bold: f('\x1b[1m', '\x1b[22m', '\x1b[22m\x1b[1m'),
|
|
94
|
+
dim: f('\x1b[2m', '\x1b[22m', '\x1b[22m\x1b[2m'),
|
|
95
|
+
italic: f('\x1b[3m', '\x1b[23m'),
|
|
96
|
+
underline: f('\x1b[4m', '\x1b[24m'),
|
|
97
|
+
inverse: f('\x1b[7m', '\x1b[27m'),
|
|
98
|
+
hidden: f('\x1b[8m', '\x1b[28m'),
|
|
99
|
+
strikethrough: f('\x1b[9m', '\x1b[29m'),
|
|
100
|
+
black: f('\x1b[30m', '\x1b[39m'),
|
|
101
|
+
red: f('\x1b[31m', '\x1b[39m'),
|
|
102
|
+
green: f('\x1b[32m', '\x1b[39m'),
|
|
103
|
+
yellow: f('\x1b[33m', '\x1b[39m'),
|
|
104
|
+
blue: f('\x1b[34m', '\x1b[39m'),
|
|
105
|
+
magenta: f('\x1b[35m', '\x1b[39m'),
|
|
106
|
+
cyan: f('\x1b[36m', '\x1b[39m'),
|
|
107
|
+
white: f('\x1b[37m', '\x1b[39m'),
|
|
108
|
+
gray: f('\x1b[90m', '\x1b[39m'),
|
|
109
|
+
bgBlack: f('\x1b[40m', '\x1b[49m'),
|
|
110
|
+
bgRed: f('\x1b[41m', '\x1b[49m'),
|
|
111
|
+
bgGreen: f('\x1b[42m', '\x1b[49m'),
|
|
112
|
+
bgYellow: f('\x1b[43m', '\x1b[49m'),
|
|
113
|
+
bgBlue: f('\x1b[44m', '\x1b[49m'),
|
|
114
|
+
bgMagenta: f('\x1b[45m', '\x1b[49m'),
|
|
115
|
+
bgCyan: f('\x1b[46m', '\x1b[49m'),
|
|
116
|
+
bgWhite: f('\x1b[47m', '\x1b[49m'),
|
|
117
|
+
blackBright: f('\x1b[90m', '\x1b[39m'),
|
|
118
|
+
redBright: f('\x1b[91m', '\x1b[39m'),
|
|
119
|
+
greenBright: f('\x1b[92m', '\x1b[39m'),
|
|
120
|
+
yellowBright: f('\x1b[93m', '\x1b[39m'),
|
|
121
|
+
blueBright: f('\x1b[94m', '\x1b[39m'),
|
|
122
|
+
magentaBright: f('\x1b[95m', '\x1b[39m'),
|
|
123
|
+
cyanBright: f('\x1b[96m', '\x1b[39m'),
|
|
124
|
+
whiteBright: f('\x1b[97m', '\x1b[39m'),
|
|
125
|
+
bgBlackBright: f('\x1b[100m', '\x1b[49m'),
|
|
126
|
+
bgRedBright: f('\x1b[101m', '\x1b[49m'),
|
|
127
|
+
bgGreenBright: f('\x1b[102m', '\x1b[49m'),
|
|
128
|
+
bgYellowBright: f('\x1b[103m', '\x1b[49m'),
|
|
129
|
+
bgBlueBright: f('\x1b[104m', '\x1b[49m'),
|
|
130
|
+
bgMagentaBright: f('\x1b[105m', '\x1b[49m'),
|
|
131
|
+
bgCyanBright: f('\x1b[106m', '\x1b[49m'),
|
|
132
|
+
bgWhiteBright: f('\x1b[107m', '\x1b[49m'),
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
const pc = createColors()
|
|
137
|
+
|
|
138
|
+
export { createColors }
|
|
139
|
+
export type { PicoColors }
|
|
140
|
+
export default pc
|