@react-native-harness/tools 1.0.0-alpha.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/LICENSE +20 -0
- package/README.md +7 -0
- package/dist/abort.d.ts +2 -0
- package/dist/abort.d.ts.map +1 -0
- package/dist/abort.js +5 -0
- package/dist/color.d.ts +3 -0
- package/dist/color.d.ts.map +1 -0
- package/dist/color.js +2 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6 -0
- package/dist/isInteractive.d.ts +9 -0
- package/dist/isInteractive.d.ts.map +1 -0
- package/dist/isInteractive.js +9 -0
- package/dist/logger.d.ts +11 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +57 -0
- package/dist/prompts.d.ts +30 -0
- package/dist/prompts.d.ts.map +1 -0
- package/dist/prompts.js +121 -0
- package/dist/react-native.d.ts +5 -0
- package/dist/react-native.d.ts.map +1 -0
- package/dist/react-native.js +23 -0
- package/dist/spawn.d.ts +7 -0
- package/dist/spawn.d.ts.map +1 -0
- package/dist/spawn.js +50 -0
- package/dist/tsconfig.lib.tsbuildinfo +1 -0
- package/eslint.config.mjs +19 -0
- package/package.json +23 -0
- package/src/abort.ts +5 -0
- package/src/color.ts +3 -0
- package/src/index.ts +6 -0
- package/src/isInteractive.ts +11 -0
- package/src/logger.ts +72 -0
- package/src/prompts.ts +169 -0
- package/src/react-native.ts +27 -0
- package/src/spawn.ts +65 -0
- package/tsconfig.json +10 -0
- package/tsconfig.lib.json +14 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Callstack
|
|
4
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
5
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
6
|
+
in the Software without restriction, including without limitation the rights
|
|
7
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
8
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
9
|
+
furnished to do so, subject to the following conditions:
|
|
10
|
+
|
|
11
|
+
The above copyright notice and this permission notice shall be included in all
|
|
12
|
+
copies or substantial portions of the Software.
|
|
13
|
+
|
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
15
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
16
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
17
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
18
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
19
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
20
|
+
SOFTWARE.
|
package/README.md
ADDED
package/dist/abort.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"abort.d.ts","sourceRoot":"","sources":["../src/abort.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,gBAAgB,GAAI,SAAS,MAAM,KAAG,WAIlD,CAAC"}
|
package/dist/abort.js
ADDED
package/dist/color.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"color.d.ts","sourceRoot":"","sources":["../src/color.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,YAAY,CAAC;AAE/B,OAAO,EAAE,KAAK,EAAE,CAAC"}
|
package/dist/color.js
ADDED
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC;AAC3B,cAAc,mBAAmB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Source from https://github.com/sindresorhus/is-interactive/blob/main/index.js
|
|
3
|
+
*/
|
|
4
|
+
export declare const isInteractive: ({ stream }?: {
|
|
5
|
+
stream?: (NodeJS.WriteStream & {
|
|
6
|
+
fd: 1;
|
|
7
|
+
}) | undefined;
|
|
8
|
+
}) => boolean;
|
|
9
|
+
//# sourceMappingURL=isInteractive.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"isInteractive.d.ts","sourceRoot":"","sources":["../src/isInteractive.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,eAAO,MAAM,aAAa,GAAI;;;;CAAgC,YAO7D,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Source from https://github.com/sindresorhus/is-interactive/blob/main/index.js
|
|
3
|
+
*/
|
|
4
|
+
export const isInteractive = ({ stream = process.stdout } = {}) => {
|
|
5
|
+
return Boolean(stream &&
|
|
6
|
+
stream.isTTY &&
|
|
7
|
+
process.env['TERM'] !== 'dumb' &&
|
|
8
|
+
!('CI' in process.env));
|
|
9
|
+
};
|
package/dist/logger.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export declare const logger: {
|
|
2
|
+
success: (...messages: Array<unknown>) => void;
|
|
3
|
+
info: (...messages: Array<unknown>) => void;
|
|
4
|
+
warn: (...messages: Array<unknown>) => void;
|
|
5
|
+
error: (...messages: Array<unknown>) => void;
|
|
6
|
+
debug: (...messages: Array<unknown>) => void;
|
|
7
|
+
log: (...messages: Array<unknown>) => void;
|
|
8
|
+
setVerbose: (level: boolean) => void;
|
|
9
|
+
isVerbose: () => boolean;
|
|
10
|
+
};
|
|
11
|
+
//# sourceMappingURL=logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AA0DA,eAAO,MAAM,MAAM;2BA3CW,KAAK,CAAC,OAAO,CAAC;wBAKjB,KAAK,CAAC,OAAO,CAAC;wBAKd,KAAK,CAAC,OAAO,CAAC;yBAKb,KAAK,CAAC,OAAO,CAAC;yBAUd,KAAK,CAAC,OAAO,CAAC;uBALhB,KAAK,CAAC,OAAO,CAAC;wBAcb,OAAO;;CAkBjC,CAAC"}
|
package/dist/logger.js
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import util from 'node:util';
|
|
2
|
+
import { log as clackLog } from '@clack/prompts';
|
|
3
|
+
import isUnicodeSupported from 'is-unicode-supported';
|
|
4
|
+
import { color } from './color.js';
|
|
5
|
+
import { isInteractive } from './isInteractive.js';
|
|
6
|
+
const unicode = isUnicodeSupported();
|
|
7
|
+
const unicodeWithFallback = (c, fallback) => unicode ? c : fallback;
|
|
8
|
+
const SYMBOL_DEBUG = unicodeWithFallback('●', '•');
|
|
9
|
+
let verbose = false;
|
|
10
|
+
const success = (...messages) => {
|
|
11
|
+
const output = util.format(...messages);
|
|
12
|
+
clackLog.success(output);
|
|
13
|
+
};
|
|
14
|
+
const info = (...messages) => {
|
|
15
|
+
const output = util.format(...messages);
|
|
16
|
+
clackLog.info(output);
|
|
17
|
+
};
|
|
18
|
+
const warn = (...messages) => {
|
|
19
|
+
const output = util.format(...messages);
|
|
20
|
+
clackLog.warn(mapLines(output, color.yellow));
|
|
21
|
+
};
|
|
22
|
+
const error = (...messages) => {
|
|
23
|
+
const output = util.format(...messages);
|
|
24
|
+
clackLog.error(mapLines(output, color.red));
|
|
25
|
+
};
|
|
26
|
+
const log = (...messages) => {
|
|
27
|
+
const output = util.format(...messages);
|
|
28
|
+
clackLog.step(output);
|
|
29
|
+
};
|
|
30
|
+
const debug = (...messages) => {
|
|
31
|
+
if (verbose) {
|
|
32
|
+
const output = util.format(...messages);
|
|
33
|
+
clackLog.message(mapLines(output, color.dim), {
|
|
34
|
+
symbol: color.dim(SYMBOL_DEBUG),
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
const setVerbose = (level) => {
|
|
39
|
+
verbose = level;
|
|
40
|
+
};
|
|
41
|
+
const isVerbose = () => {
|
|
42
|
+
// For non-interactive environments, always show verbose logs
|
|
43
|
+
return !isInteractive() || verbose;
|
|
44
|
+
};
|
|
45
|
+
export const logger = {
|
|
46
|
+
success,
|
|
47
|
+
info,
|
|
48
|
+
warn,
|
|
49
|
+
error,
|
|
50
|
+
debug,
|
|
51
|
+
log,
|
|
52
|
+
setVerbose,
|
|
53
|
+
isVerbose,
|
|
54
|
+
};
|
|
55
|
+
function mapLines(text, colorFn) {
|
|
56
|
+
return text.split('\n').map(colorFn).join('\n');
|
|
57
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import * as clack from '@clack/prompts';
|
|
2
|
+
export declare const intro: (title?: string) => void;
|
|
3
|
+
export declare const outro: (message?: string) => void;
|
|
4
|
+
export declare const note: (message?: string, title?: string) => void;
|
|
5
|
+
export declare const promptText: (options: clack.TextOptions) => Promise<string>;
|
|
6
|
+
export declare const promptPassword: (options: clack.PasswordOptions) => Promise<string>;
|
|
7
|
+
export declare const promptSelect: <T>(options: clack.SelectOptions<T>) => Promise<T>;
|
|
8
|
+
type ConfirmOptions = {
|
|
9
|
+
message: string;
|
|
10
|
+
confirmLabel?: string;
|
|
11
|
+
cancelLabel?: string;
|
|
12
|
+
};
|
|
13
|
+
export declare const promptConfirm: (options: ConfirmOptions) => Promise<boolean>;
|
|
14
|
+
export declare const promptMultiselect: <T>(options: clack.MultiSelectOptions<T>) => Promise<T[]>;
|
|
15
|
+
export declare const promptGroup: <T>(prompts: clack.PromptGroup<T>, options?: clack.PromptGroupOptions<T> | undefined) => Promise<T>;
|
|
16
|
+
export declare const spinner: (options?: clack.SpinnerOptions) => {
|
|
17
|
+
start: (message?: string) => void;
|
|
18
|
+
stop: (message?: string, code?: number) => void;
|
|
19
|
+
message: (message?: string) => void;
|
|
20
|
+
};
|
|
21
|
+
export declare const progress: (options?: clack.ProgressOptions) => {
|
|
22
|
+
start: (message?: string) => void;
|
|
23
|
+
advance: (_: number, message?: string) => void;
|
|
24
|
+
stop: (message?: string, code?: number) => void;
|
|
25
|
+
message: (message?: string) => void;
|
|
26
|
+
};
|
|
27
|
+
export declare const formatStartMessage: (text: string | undefined) => string | undefined;
|
|
28
|
+
export declare const cancelPromptAndExit: (message?: string) => never;
|
|
29
|
+
export {};
|
|
30
|
+
//# sourceMappingURL=prompts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../src/prompts.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,gBAAgB,CAAC;AAIxC,eAAO,MAAM,KAAK,GAAI,QAAQ,MAAM,SAAuB,CAAC;AAE5D,eAAO,MAAM,KAAK,GAAI,UAAU,MAAM,SAAyB,CAAC;AAEhE,eAAO,MAAM,IAAI,GAAI,UAAU,MAAM,EAAE,QAAQ,MAAM,SACzB,CAAC;AAE7B,eAAO,MAAM,UAAU,GACrB,SAAS,KAAK,CAAC,WAAW,KACzB,OAAO,CAAC,MAAM,CAOhB,CAAC;AAEF,eAAO,MAAM,cAAc,GACzB,SAAS,KAAK,CAAC,eAAe,KAC7B,OAAO,CAAC,MAAM,CAOhB,CAAC;AAEF,eAAO,MAAM,YAAY,GAAU,CAAC,EAClC,SAAS,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,KAC9B,OAAO,CAAC,CAAC,CAYX,CAAC;AAEF,KAAK,cAAc,GAAG;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,eAAO,MAAM,aAAa,GACxB,SAAS,cAAc,KACtB,OAAO,CAAC,OAAO,CAcjB,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAAU,CAAC,EACvC,SAAS,KAAK,CAAC,kBAAkB,CAAC,CAAC,CAAC,KACnC,OAAO,CAAC,CAAC,EAAE,CAOb,CAAC;AAEF,eAAO,MAAM,WAAW,GAAU,CAAC,EACjC,SAAS,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,EAC7B,UAAU,KAAK,CAAC,kBAAkB,CAAC,CAAC,CAAC,GAAG,SAAS,KAChD,OAAO,CAAC,CAAC,CAOX,CAAC;AAEF,eAAO,MAAM,OAAO,GAAI,UAAU,KAAK,CAAC,cAAc;sBAG9B,MAAM;qBACP,MAAM;wBAGH,MAAM;CAiB/B,CAAC;AAEF,eAAO,MAAM,QAAQ,GAAI,UAAU,KAAK,CAAC,eAAe;sBAGhC,MAAM;iBACX,MAAM,YAAY,MAAM;qBAGpB,MAAM;wBAGH,MAAM;CAoB/B,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAC7B,MAAM,MAAM,GAAG,SAAS,KACvB,MAAM,GAAG,SAOX,CAAC;AAEF,eAAO,MAAM,mBAAmB,GAAI,UAAU,MAAM,KAAG,KAGtD,CAAC"}
|
package/dist/prompts.js
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import * as clack from '@clack/prompts';
|
|
2
|
+
import { isInteractive } from './isInteractive.js';
|
|
3
|
+
import { logger } from './logger.js';
|
|
4
|
+
export const intro = (title) => clack.intro(title);
|
|
5
|
+
export const outro = (message) => clack.outro(message);
|
|
6
|
+
export const note = (message, title) => clack.note(message, title);
|
|
7
|
+
export const promptText = async (options) => {
|
|
8
|
+
const result = await clack.text(options);
|
|
9
|
+
if (clack.isCancel(result)) {
|
|
10
|
+
cancelPromptAndExit();
|
|
11
|
+
}
|
|
12
|
+
return result;
|
|
13
|
+
};
|
|
14
|
+
export const promptPassword = async (options) => {
|
|
15
|
+
const result = await clack.password(options);
|
|
16
|
+
if (clack.isCancel(result)) {
|
|
17
|
+
cancelPromptAndExit();
|
|
18
|
+
}
|
|
19
|
+
return result;
|
|
20
|
+
};
|
|
21
|
+
export const promptSelect = async (options) => {
|
|
22
|
+
// If there is only one option, return it immediately
|
|
23
|
+
if (options.options.length === 1) {
|
|
24
|
+
return options.options[0].value;
|
|
25
|
+
}
|
|
26
|
+
const result = await clack.select(options);
|
|
27
|
+
if (clack.isCancel(result)) {
|
|
28
|
+
cancelPromptAndExit();
|
|
29
|
+
}
|
|
30
|
+
return result;
|
|
31
|
+
};
|
|
32
|
+
export const promptConfirm = async (options) => {
|
|
33
|
+
const result = await clack.select({
|
|
34
|
+
message: options.message,
|
|
35
|
+
options: [
|
|
36
|
+
{ value: true, label: options.confirmLabel ?? 'Confirm' },
|
|
37
|
+
{ value: false, label: options.cancelLabel ?? 'Cancel' },
|
|
38
|
+
],
|
|
39
|
+
});
|
|
40
|
+
if (clack.isCancel(result)) {
|
|
41
|
+
cancelPromptAndExit();
|
|
42
|
+
}
|
|
43
|
+
return result === true;
|
|
44
|
+
};
|
|
45
|
+
export const promptMultiselect = async (options) => {
|
|
46
|
+
const result = await clack.multiselect(options);
|
|
47
|
+
if (clack.isCancel(result)) {
|
|
48
|
+
cancelPromptAndExit();
|
|
49
|
+
}
|
|
50
|
+
return result;
|
|
51
|
+
};
|
|
52
|
+
export const promptGroup = async (prompts, options) => {
|
|
53
|
+
const result = await clack.group(prompts, options);
|
|
54
|
+
if (clack.isCancel(result)) {
|
|
55
|
+
cancelPromptAndExit();
|
|
56
|
+
}
|
|
57
|
+
return result;
|
|
58
|
+
};
|
|
59
|
+
export const spinner = (options) => {
|
|
60
|
+
if (logger.isVerbose() || !isInteractive()) {
|
|
61
|
+
return {
|
|
62
|
+
start: (message) => logger.log(formatStartMessage(message)),
|
|
63
|
+
stop: (message, code = 0) => {
|
|
64
|
+
return code === 0 ? logger.log(message) : logger.error(message);
|
|
65
|
+
},
|
|
66
|
+
message: (message) => logger.log(formatStartMessage(message)),
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
const clackSpinner = clack.spinner(options);
|
|
70
|
+
return {
|
|
71
|
+
start: (message) => {
|
|
72
|
+
clackSpinner.start(message);
|
|
73
|
+
},
|
|
74
|
+
stop: (message, code) => {
|
|
75
|
+
clackSpinner.stop(message, code);
|
|
76
|
+
},
|
|
77
|
+
message: (message) => {
|
|
78
|
+
clackSpinner.message(message);
|
|
79
|
+
},
|
|
80
|
+
};
|
|
81
|
+
};
|
|
82
|
+
export const progress = (options) => {
|
|
83
|
+
if (logger.isVerbose() || !isInteractive()) {
|
|
84
|
+
return {
|
|
85
|
+
start: (message) => logger.log(formatStartMessage(message)),
|
|
86
|
+
advance: (_, message) => {
|
|
87
|
+
logger.log(formatStartMessage(message));
|
|
88
|
+
},
|
|
89
|
+
stop: (message, code = 0) => {
|
|
90
|
+
return code === 0 ? logger.log(message) : logger.error(message);
|
|
91
|
+
},
|
|
92
|
+
message: (message) => logger.log(formatStartMessage(message)),
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
const clackProgress = clack.progress(options);
|
|
96
|
+
return {
|
|
97
|
+
start: (message) => {
|
|
98
|
+
clackProgress.start(message);
|
|
99
|
+
},
|
|
100
|
+
advance: (value, message) => {
|
|
101
|
+
clackProgress.advance(value, message);
|
|
102
|
+
},
|
|
103
|
+
stop: (message, code = 0) => {
|
|
104
|
+
clackProgress.stop(message, code);
|
|
105
|
+
},
|
|
106
|
+
message: (message) => {
|
|
107
|
+
clackProgress.message(message);
|
|
108
|
+
},
|
|
109
|
+
};
|
|
110
|
+
};
|
|
111
|
+
export const formatStartMessage = (text) => {
|
|
112
|
+
if (text === undefined) {
|
|
113
|
+
return undefined;
|
|
114
|
+
}
|
|
115
|
+
const messageWithoutDots = text.replace(/\.+$/, '');
|
|
116
|
+
return `${messageWithoutDots}...`;
|
|
117
|
+
};
|
|
118
|
+
export const cancelPromptAndExit = (message) => {
|
|
119
|
+
clack.cancel(message ?? 'Operation cancelled by user.');
|
|
120
|
+
process.exit(0);
|
|
121
|
+
};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export declare const getReactNativePackagePath: () => string;
|
|
2
|
+
export declare const getReactNativeCliPath: () => string;
|
|
3
|
+
export declare const getExpoPackagePath: () => string;
|
|
4
|
+
export declare const getExpoCliPath: () => string;
|
|
5
|
+
//# sourceMappingURL=react-native.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"react-native.d.ts","sourceRoot":"","sources":["../src/react-native.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,yBAAyB,QAAO,MAI5C,CAAA;AAED,eAAO,MAAM,qBAAqB,QAAO,MAIxC,CAAA;AAED,eAAO,MAAM,kBAAkB,QAAO,MAIrC,CAAA;AAED,eAAO,MAAM,cAAc,QAAO,MAIjC,CAAA"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { createRequire } from 'node:module';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import fs from 'node:fs';
|
|
4
|
+
export const getReactNativePackagePath = () => {
|
|
5
|
+
const require = createRequire(import.meta.url);
|
|
6
|
+
const input = require.resolve('react-native', { paths: [process.cwd()] });
|
|
7
|
+
return path.dirname(input);
|
|
8
|
+
};
|
|
9
|
+
export const getReactNativeCliPath = () => {
|
|
10
|
+
const reactNativePackagePath = getReactNativePackagePath();
|
|
11
|
+
const packageJson = JSON.parse(fs.readFileSync(path.join(reactNativePackagePath, 'package.json'), 'utf8'));
|
|
12
|
+
return path.join(reactNativePackagePath, packageJson.bin['react-native']);
|
|
13
|
+
};
|
|
14
|
+
export const getExpoPackagePath = () => {
|
|
15
|
+
const require = createRequire(import.meta.url);
|
|
16
|
+
const input = require.resolve('expo', { paths: [process.cwd()] });
|
|
17
|
+
return path.join(path.dirname(input), '..');
|
|
18
|
+
};
|
|
19
|
+
export const getExpoCliPath = () => {
|
|
20
|
+
const expoPackagePath = getExpoPackagePath();
|
|
21
|
+
const packageJson = JSON.parse(fs.readFileSync(path.join(expoPackagePath, 'package.json'), 'utf8'));
|
|
22
|
+
return path.join(expoPackagePath, packageJson.bin['expo']);
|
|
23
|
+
};
|
package/dist/spawn.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { Options, Subprocess } from 'nano-spawn';
|
|
2
|
+
import { SubprocessError } from 'nano-spawn';
|
|
3
|
+
export type SpawnOptions = Options;
|
|
4
|
+
export declare const spawn: (file: string, args?: readonly string[], options?: SpawnOptions) => Subprocess;
|
|
5
|
+
export declare const spawnAndForget: (file: string, args?: readonly string[], options?: SpawnOptions) => Promise<void>;
|
|
6
|
+
export { Subprocess, SubprocessError };
|
|
7
|
+
//# sourceMappingURL=spawn.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spawn.d.ts","sourceRoot":"","sources":["../src/spawn.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACtD,OAAkB,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAGxD,MAAM,MAAM,YAAY,GAAG,OAAO,CAAC;AAEnC,eAAO,MAAM,KAAK,GAChB,MAAM,MAAM,EACZ,OAAO,SAAS,MAAM,EAAE,EACxB,UAAU,YAAY,KACrB,UAaF,CAAC;AAEF,eAAO,MAAM,cAAc,GAAU,MAAM,MAAM,EAAE,OAAO,SAAS,MAAM,EAAE,EAAE,UAAU,YAAY,KAAG,OAAO,CAAC,IAAI,CAMjH,CAAC;AAEF,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,CAAC"}
|
package/dist/spawn.js
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import nanoSpawn, { SubprocessError } from 'nano-spawn';
|
|
2
|
+
import { logger } from './logger.js';
|
|
3
|
+
export const spawn = (file, args, options) => {
|
|
4
|
+
const defaultStream = 'pipe';
|
|
5
|
+
const defaultOptions = {
|
|
6
|
+
stdin: defaultStream,
|
|
7
|
+
stdout: defaultStream,
|
|
8
|
+
// Always 'pipe' stderr to handle errors properly down the line
|
|
9
|
+
stderr: 'pipe',
|
|
10
|
+
};
|
|
11
|
+
logger.debug(`Running: ${file}`, ...(args ?? []));
|
|
12
|
+
const childProcess = nanoSpawn(file, args, { ...defaultOptions, ...options });
|
|
13
|
+
setupChildProcessCleanup(childProcess);
|
|
14
|
+
return childProcess;
|
|
15
|
+
};
|
|
16
|
+
export const spawnAndForget = async (file, args, options) => {
|
|
17
|
+
try {
|
|
18
|
+
await spawn(file, args, options);
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
// We don't care about the error here.
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
export { SubprocessError };
|
|
25
|
+
const setupChildProcessCleanup = (childProcess) => {
|
|
26
|
+
// https://stackoverflow.com/questions/53049939/node-daemon-wont-start-with-process-stdin-setrawmodetrue/53050098#53050098
|
|
27
|
+
if (process.stdin.isTTY) {
|
|
28
|
+
// overwrite @clack/prompts setting raw mode for spinner and prompts,
|
|
29
|
+
// which prevents listening for SIGINT and SIGTERM
|
|
30
|
+
process.stdin.setRawMode(false);
|
|
31
|
+
}
|
|
32
|
+
const terminate = async () => {
|
|
33
|
+
try {
|
|
34
|
+
(await childProcess.nodeChildProcess).kill();
|
|
35
|
+
process.exit(1);
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
// ignore
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
const sigintHandler = () => terminate();
|
|
42
|
+
const sigtermHandler = () => terminate();
|
|
43
|
+
process.on('SIGINT', sigintHandler);
|
|
44
|
+
process.on('SIGTERM', sigtermHandler);
|
|
45
|
+
const cleanup = () => {
|
|
46
|
+
process.off('SIGINT', sigintHandler);
|
|
47
|
+
process.off('SIGTERM', sigtermHandler);
|
|
48
|
+
};
|
|
49
|
+
childProcess.nodeChildProcess.finally(cleanup);
|
|
50
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"fileNames":["../../../node_modules/typescript/lib/lib.es5.d.ts","../../../node_modules/typescript/lib/lib.es2015.d.ts","../../../node_modules/typescript/lib/lib.es2016.d.ts","../../../node_modules/typescript/lib/lib.es2017.d.ts","../../../node_modules/typescript/lib/lib.es2018.d.ts","../../../node_modules/typescript/lib/lib.es2019.d.ts","../../../node_modules/typescript/lib/lib.es2020.d.ts","../../../node_modules/typescript/lib/lib.es2021.d.ts","../../../node_modules/typescript/lib/lib.es2022.d.ts","../../../node_modules/typescript/lib/lib.es2015.core.d.ts","../../../node_modules/typescript/lib/lib.es2015.collection.d.ts","../../../node_modules/typescript/lib/lib.es2015.generator.d.ts","../../../node_modules/typescript/lib/lib.es2015.iterable.d.ts","../../../node_modules/typescript/lib/lib.es2015.promise.d.ts","../../../node_modules/typescript/lib/lib.es2015.proxy.d.ts","../../../node_modules/typescript/lib/lib.es2015.reflect.d.ts","../../../node_modules/typescript/lib/lib.es2015.symbol.d.ts","../../../node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts","../../../node_modules/typescript/lib/lib.es2016.array.include.d.ts","../../../node_modules/typescript/lib/lib.es2016.intl.d.ts","../../../node_modules/typescript/lib/lib.es2017.arraybuffer.d.ts","../../../node_modules/typescript/lib/lib.es2017.date.d.ts","../../../node_modules/typescript/lib/lib.es2017.object.d.ts","../../../node_modules/typescript/lib/lib.es2017.sharedmemory.d.ts","../../../node_modules/typescript/lib/lib.es2017.string.d.ts","../../../node_modules/typescript/lib/lib.es2017.intl.d.ts","../../../node_modules/typescript/lib/lib.es2017.typedarrays.d.ts","../../../node_modules/typescript/lib/lib.es2018.asyncgenerator.d.ts","../../../node_modules/typescript/lib/lib.es2018.asynciterable.d.ts","../../../node_modules/typescript/lib/lib.es2018.intl.d.ts","../../../node_modules/typescript/lib/lib.es2018.promise.d.ts","../../../node_modules/typescript/lib/lib.es2018.regexp.d.ts","../../../node_modules/typescript/lib/lib.es2019.array.d.ts","../../../node_modules/typescript/lib/lib.es2019.object.d.ts","../../../node_modules/typescript/lib/lib.es2019.string.d.ts","../../../node_modules/typescript/lib/lib.es2019.symbol.d.ts","../../../node_modules/typescript/lib/lib.es2019.intl.d.ts","../../../node_modules/typescript/lib/lib.es2020.bigint.d.ts","../../../node_modules/typescript/lib/lib.es2020.date.d.ts","../../../node_modules/typescript/lib/lib.es2020.promise.d.ts","../../../node_modules/typescript/lib/lib.es2020.sharedmemory.d.ts","../../../node_modules/typescript/lib/lib.es2020.string.d.ts","../../../node_modules/typescript/lib/lib.es2020.symbol.wellknown.d.ts","../../../node_modules/typescript/lib/lib.es2020.intl.d.ts","../../../node_modules/typescript/lib/lib.es2020.number.d.ts","../../../node_modules/typescript/lib/lib.es2021.promise.d.ts","../../../node_modules/typescript/lib/lib.es2021.string.d.ts","../../../node_modules/typescript/lib/lib.es2021.weakref.d.ts","../../../node_modules/typescript/lib/lib.es2021.intl.d.ts","../../../node_modules/typescript/lib/lib.es2022.array.d.ts","../../../node_modules/typescript/lib/lib.es2022.error.d.ts","../../../node_modules/typescript/lib/lib.es2022.intl.d.ts","../../../node_modules/typescript/lib/lib.es2022.object.d.ts","../../../node_modules/typescript/lib/lib.es2022.string.d.ts","../../../node_modules/typescript/lib/lib.es2022.regexp.d.ts","../../../node_modules/typescript/lib/lib.esnext.intl.d.ts","../../../node_modules/typescript/lib/lib.decorators.d.ts","../../../node_modules/typescript/lib/lib.decorators.legacy.d.ts","../../../node_modules/tslib/tslib.d.ts","../../../node_modules/tslib/modules/index.d.ts","../src/abort.ts","../../../node_modules/picocolors/types.d.ts","../../../node_modules/picocolors/picocolors.d.ts","../src/color.ts","../../../node_modules/@clack/core/dist/index.d.mts","../../../node_modules/@clack/prompts/dist/index.d.mts","../../../node_modules/is-unicode-supported/index.d.ts","../src/isinteractive.ts","../src/logger.ts","../src/prompts.ts","../../../node_modules/nano-spawn/source/index.d.ts","../src/spawn.ts","../src/react-native.ts","../src/index.ts","../../../node_modules/@types/node/assert.d.ts","../../../node_modules/@types/node/assert/strict.d.ts","../../../node_modules/@types/node/globals.d.ts","../../../node_modules/@types/node/async_hooks.d.ts","../../../node_modules/@types/node/buffer.d.ts","../../../node_modules/@types/node/child_process.d.ts","../../../node_modules/@types/node/cluster.d.ts","../../../node_modules/@types/node/console.d.ts","../../../node_modules/@types/node/constants.d.ts","../../../node_modules/@types/node/crypto.d.ts","../../../node_modules/@types/node/dgram.d.ts","../../../node_modules/@types/node/diagnostics_channel.d.ts","../../../node_modules/@types/node/dns.d.ts","../../../node_modules/@types/node/dns/promises.d.ts","../../../node_modules/@types/node/domain.d.ts","../../../node_modules/@types/node/dom-events.d.ts","../../../node_modules/@types/node/events.d.ts","../../../node_modules/@types/node/fs.d.ts","../../../node_modules/@types/node/fs/promises.d.ts","../../../node_modules/@types/node/http.d.ts","../../../node_modules/@types/node/http2.d.ts","../../../node_modules/@types/node/https.d.ts","../../../node_modules/@types/node/inspector.d.ts","../../../node_modules/@types/node/module.d.ts","../../../node_modules/@types/node/net.d.ts","../../../node_modules/@types/node/os.d.ts","../../../node_modules/@types/node/path.d.ts","../../../node_modules/@types/node/perf_hooks.d.ts","../../../node_modules/@types/node/process.d.ts","../../../node_modules/@types/node/punycode.d.ts","../../../node_modules/@types/node/querystring.d.ts","../../../node_modules/@types/node/readline.d.ts","../../../node_modules/@types/node/readline/promises.d.ts","../../../node_modules/@types/node/repl.d.ts","../../../node_modules/@types/node/stream.d.ts","../../../node_modules/@types/node/stream/promises.d.ts","../../../node_modules/@types/node/stream/consumers.d.ts","../../../node_modules/@types/node/stream/web.d.ts","../../../node_modules/@types/node/string_decoder.d.ts","../../../node_modules/@types/node/test.d.ts","../../../node_modules/@types/node/timers.d.ts","../../../node_modules/@types/node/timers/promises.d.ts","../../../node_modules/@types/node/tls.d.ts","../../../node_modules/@types/node/trace_events.d.ts","../../../node_modules/@types/node/tty.d.ts","../../../node_modules/@types/node/url.d.ts","../../../node_modules/@types/node/util.d.ts","../../../node_modules/@types/node/v8.d.ts","../../../node_modules/@types/node/vm.d.ts","../../../node_modules/@types/node/wasi.d.ts","../../../node_modules/@types/node/worker_threads.d.ts","../../../node_modules/@types/node/zlib.d.ts","../../../node_modules/@types/node/globals.global.d.ts","../../../node_modules/@types/node/index.d.ts"],"fileIdsList":[[106,109,121],[65,109,121],[75,121],[78,121],[79,84,112,121],[80,91,92,99,109,120,121],[80,81,91,99,121],[82,121],[83,84,92,100,121],[84,109,117,121],[85,87,91,99,121],[86,121],[87,88,121],[91,121],[89,91,121],[91,92,93,109,120,121],[91,92,93,106,109,112,121],[121,125],[121],[87,91,94,99,109,120,121],[91,92,94,95,99,109,117,120,121],[94,96,109,117,120,121],[75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127],[91,97,121],[98,120,121],[87,91,99,109,121],[100,121],[101,121],[78,102,121],[103,119,121,125],[104,121],[105,121],[91,106,107,121],[106,108,121,123],[79,91,109,110,111,112,121],[79,109,111,121],[109,110,121],[112,121],[113,121],[91,115,116,121],[115,116,121],[84,99,109,117,121],[118,121],[99,119,121],[79,94,105,120,121],[84,121],[109,121,122],[121,123],[121,124],[79,84,91,93,102,109,120,121,123,125],[109,121,126],[80,121],[62,121],[59,121],[60,121],[60,63,121],[60,61,64,69,70,72,73,121],[60,64,66,67,68,121],[60,66,68,69,121],[60,92,98,101,121],[60,69,71,121]],"fileInfos":[{"version":"69684132aeb9b5642cbcd9e22dff7818ff0ee1aa831728af0ecf97d3364d5546","affectsGlobalScope":true,"impliedFormat":1},{"version":"45b7ab580deca34ae9729e97c13cfd999df04416a79116c3bfb483804f85ded4","impliedFormat":1},{"version":"3facaf05f0c5fc569c5649dd359892c98a85557e3e0c847964caeb67076f4d75","impliedFormat":1},{"version":"e44bb8bbac7f10ecc786703fe0a6a4b952189f908707980ba8f3c8975a760962","impliedFormat":1},{"version":"5e1c4c362065a6b95ff952c0eab010f04dcd2c3494e813b493ecfd4fcb9fc0d8","impliedFormat":1},{"version":"68d73b4a11549f9c0b7d352d10e91e5dca8faa3322bfb77b661839c42b1ddec7","impliedFormat":1},{"version":"5efce4fc3c29ea84e8928f97adec086e3dc876365e0982cc8479a07954a3efd4","impliedFormat":1},{"version":"feecb1be483ed332fad555aff858affd90a48ab19ba7272ee084704eb7167569","impliedFormat":1},{"version":"ee7bad0c15b58988daa84371e0b89d313b762ab83cb5b31b8a2d1162e8eb41c2","impliedFormat":1},{"version":"c57796738e7f83dbc4b8e65132f11a377649c00dd3eee333f672b8f0a6bea671","affectsGlobalScope":true,"impliedFormat":1},{"version":"dc2df20b1bcdc8c2d34af4926e2c3ab15ffe1160a63e58b7e09833f616efff44","affectsGlobalScope":true,"impliedFormat":1},{"version":"515d0b7b9bea2e31ea4ec968e9edd2c39d3eebf4a2d5cbd04e88639819ae3b71","affectsGlobalScope":true,"impliedFormat":1},{"version":"0559b1f683ac7505ae451f9a96ce4c3c92bdc71411651ca6ddb0e88baaaad6a3","affectsGlobalScope":true,"impliedFormat":1},{"version":"0dc1e7ceda9b8b9b455c3a2d67b0412feab00bd2f66656cd8850e8831b08b537","affectsGlobalScope":true,"impliedFormat":1},{"version":"ce691fb9e5c64efb9547083e4a34091bcbe5bdb41027e310ebba8f7d96a98671","affectsGlobalScope":true,"impliedFormat":1},{"version":"8d697a2a929a5fcb38b7a65594020fcef05ec1630804a33748829c5ff53640d0","affectsGlobalScope":true,"impliedFormat":1},{"version":"4ff2a353abf8a80ee399af572debb8faab2d33ad38c4b4474cff7f26e7653b8d","affectsGlobalScope":true,"impliedFormat":1},{"version":"936e80ad36a2ee83fc3caf008e7c4c5afe45b3cf3d5c24408f039c1d47bdc1df","affectsGlobalScope":true,"impliedFormat":1},{"version":"d15bea3d62cbbdb9797079416b8ac375ae99162a7fba5de2c6c505446486ac0a","affectsGlobalScope":true,"impliedFormat":1},{"version":"68d18b664c9d32a7336a70235958b8997ebc1c3b8505f4f1ae2b7e7753b87618","affectsGlobalScope":true,"impliedFormat":1},{"version":"eb3d66c8327153d8fa7dd03f9c58d351107fe824c79e9b56b462935176cdf12a","affectsGlobalScope":true,"impliedFormat":1},{"version":"38f0219c9e23c915ef9790ab1d680440d95419ad264816fa15009a8851e79119","affectsGlobalScope":true,"impliedFormat":1},{"version":"69ab18c3b76cd9b1be3d188eaf8bba06112ebbe2f47f6c322b5105a6fbc45a2e","affectsGlobalScope":true,"impliedFormat":1},{"version":"fef8cfad2e2dc5f5b3d97a6f4f2e92848eb1b88e897bb7318cef0e2820bceaab","affectsGlobalScope":true,"impliedFormat":1},{"version":"2f11ff796926e0832f9ae148008138ad583bd181899ab7dd768a2666700b1893","affectsGlobalScope":true,"impliedFormat":1},{"version":"4de680d5bb41c17f7f68e0419412ca23c98d5749dcaaea1896172f06435891fc","affectsGlobalScope":true,"impliedFormat":1},{"version":"954296b30da6d508a104a3a0b5d96b76495c709785c1d11610908e63481ee667","affectsGlobalScope":true,"impliedFormat":1},{"version":"ac9538681b19688c8eae65811b329d3744af679e0bdfa5d842d0e32524c73e1c","affectsGlobalScope":true,"impliedFormat":1},{"version":"0a969edff4bd52585473d24995c5ef223f6652d6ef46193309b3921d65dd4376","affectsGlobalScope":true,"impliedFormat":1},{"version":"9e9fbd7030c440b33d021da145d3232984c8bb7916f277e8ffd3dc2e3eae2bdb","affectsGlobalScope":true,"impliedFormat":1},{"version":"811ec78f7fefcabbda4bfa93b3eb67d9ae166ef95f9bff989d964061cbf81a0c","affectsGlobalScope":true,"impliedFormat":1},{"version":"717937616a17072082152a2ef351cb51f98802fb4b2fdabd32399843875974ca","affectsGlobalScope":true,"impliedFormat":1},{"version":"d7e7d9b7b50e5f22c915b525acc5a49a7a6584cf8f62d0569e557c5cfc4b2ac2","affectsGlobalScope":true,"impliedFormat":1},{"version":"71c37f4c9543f31dfced6c7840e068c5a5aacb7b89111a4364b1d5276b852557","affectsGlobalScope":true,"impliedFormat":1},{"version":"576711e016cf4f1804676043e6a0a5414252560eb57de9faceee34d79798c850","affectsGlobalScope":true,"impliedFormat":1},{"version":"89c1b1281ba7b8a96efc676b11b264de7a8374c5ea1e6617f11880a13fc56dc6","affectsGlobalScope":true,"impliedFormat":1},{"version":"74f7fa2d027d5b33eb0471c8e82a6c87216223181ec31247c357a3e8e2fddc5b","affectsGlobalScope":true,"impliedFormat":1},{"version":"d6d7ae4d1f1f3772e2a3cde568ed08991a8ae34a080ff1151af28b7f798e22ca","affectsGlobalScope":true,"impliedFormat":1},{"version":"063600664504610fe3e99b717a1223f8b1900087fab0b4cad1496a114744f8df","affectsGlobalScope":true,"impliedFormat":1},{"version":"934019d7e3c81950f9a8426d093458b65d5aff2c7c1511233c0fd5b941e608ab","affectsGlobalScope":true,"impliedFormat":1},{"version":"52ada8e0b6e0482b728070b7639ee42e83a9b1c22d205992756fe020fd9f4a47","affectsGlobalScope":true,"impliedFormat":1},{"version":"3bdefe1bfd4d6dee0e26f928f93ccc128f1b64d5d501ff4a8cf3c6371200e5e6","affectsGlobalScope":true,"impliedFormat":1},{"version":"59fb2c069260b4ba00b5643b907ef5d5341b167e7d1dbf58dfd895658bda2867","affectsGlobalScope":true,"impliedFormat":1},{"version":"639e512c0dfc3fad96a84caad71b8834d66329a1f28dc95e3946c9b58176c73a","affectsGlobalScope":true,"impliedFormat":1},{"version":"368af93f74c9c932edd84c58883e736c9e3d53cec1fe24c0b0ff451f529ceab1","affectsGlobalScope":true,"impliedFormat":1},{"version":"af3dd424cf267428f30ccfc376f47a2c0114546b55c44d8c0f1d57d841e28d74","affectsGlobalScope":true,"impliedFormat":1},{"version":"995c005ab91a498455ea8dfb63aa9f83fa2ea793c3d8aa344be4a1678d06d399","affectsGlobalScope":true,"impliedFormat":1},{"version":"959d36cddf5e7d572a65045b876f2956c973a586da58e5d26cde519184fd9b8a","affectsGlobalScope":true,"impliedFormat":1},{"version":"965f36eae237dd74e6cca203a43e9ca801ce38824ead814728a2807b1910117d","affectsGlobalScope":true,"impliedFormat":1},{"version":"3925a6c820dcb1a06506c90b1577db1fdbf7705d65b62b99dce4be75c637e26b","affectsGlobalScope":true,"impliedFormat":1},{"version":"0a3d63ef2b853447ec4f749d3f368ce642264246e02911fcb1590d8c161b8005","affectsGlobalScope":true,"impliedFormat":1},{"version":"b5ce7a470bc3628408429040c4e3a53a27755022a32fd05e2cb694e7015386c7","affectsGlobalScope":true,"impliedFormat":1},{"version":"8444af78980e3b20b49324f4a16ba35024fef3ee069a0eb67616ea6ca821c47a","affectsGlobalScope":true,"impliedFormat":1},{"version":"3287d9d085fbd618c3971944b65b4be57859f5415f495b33a6adc994edd2f004","affectsGlobalScope":true,"impliedFormat":1},{"version":"b4b67b1a91182421f5df999988c690f14d813b9850b40acd06ed44691f6727ad","affectsGlobalScope":true,"impliedFormat":1},{"version":"811c71eee4aa0ac5f7adf713323a5c41b0cf6c4e17367a34fbce379e12bbf0a4","affectsGlobalScope":true,"impliedFormat":1},{"version":"8e7f8264d0fb4c5339605a15daadb037bf238c10b654bb3eee14208f860a32ea","affectsGlobalScope":true,"impliedFormat":1},{"version":"782dec38049b92d4e85c1585fbea5474a219c6984a35b004963b00beb1aab538","affectsGlobalScope":true,"impliedFormat":1},{"version":"a6a5253138c5432c68a1510c70fe78a644fe2e632111ba778e1978010d6edfec","impliedFormat":1},{"version":"b8f34dd1757f68e03262b1ca3ddfa668a855b872f8bdd5224d6f993a7b37dc2c","impliedFormat":99},{"version":"d28bd70c2f363bce3ce9d5b10a96e816c8d803c556541fd9c791bf79f5890257","signature":"3e442c402123b264ccdf7123c1366e1473d9c39f5db69373e938284fc01c49ce","impliedFormat":99},{"version":"590595c1230ebb7c43ebac51b2b2da956a719b213355b4358e2a6b16a8b5936c","impliedFormat":1},{"version":"8c5f0739f00f89f89b03a1fe6658c6d78000d7ebd7f556f0f8d6908fa679de35","impliedFormat":1},{"version":"9671090691def46862e9dac962b8f8f2192e130b61ae050a1e6e050ca658adff","signature":"a15c0df1ac9b2a4d833490522614fc57ae97d70a07bf4964a4d6bb73f3f56399","impliedFormat":99},{"version":"e191585a6a460d89791b3d3d39a10607bbcefa7f7c9812af6ca5f11c33d398d1","impliedFormat":99},{"version":"24379e38ef6db808a7aed9b162dae44d16f84f63c04994efb8b0106bcc589909","impliedFormat":99},{"version":"c8f690affb73ba834a172db308a406246b3a2a30c4e4992a2f145d50e5f6a8f6","impliedFormat":1},{"version":"b49866907ab7c06bdd5768601d77314973d36ddcd9d241f8bca0ac9152c0c6d1","signature":"20666143132be33320b033fe7e995c3ce1dcd82585ec140bc833d2abe0bc927a","impliedFormat":99},{"version":"c3f43a43ea7b528b1a120c1cf9641e29cee9d888930595dc68be87cbb3e08c85","signature":"e4cead4a8596a6f051c36ef184f5fb6f117232eefdc1f98ef9847c9efc2c8911","impliedFormat":99},{"version":"e525aa1d3e33f1250b0752d5685394f4699d28209413adde404459fe04833096","signature":"8af66ec621033f41ccb2bcee775e883c2649fa0db71192fe863185b0281082a6","impliedFormat":99},{"version":"9d4af7bde3e345d3071b5fefbece2d3482971aae89ded50f302c8cb246e81581","impliedFormat":99},{"version":"9f2ba2c851681736f0271772ffa235e3d214dbe35bd7a3a8aacbb0922f8cd0e7","signature":"f3eb748185038bca941a02994b1b0b5803c0a2ce818b8a7d72a24a6b814f5d3e","impliedFormat":99},{"version":"802fb76ab6af6feb2e301b96a656c347a78c04ada0371f7bd8ea0e4fe833634d","signature":"2ba26b5ab00dd3495eeb733cdb46d939a8eb755a395a91169158cdf962aff6c3","impliedFormat":99},{"version":"0b6ab4dd18ad8a97b426b3c0ce54d5e27743ab39789e4969b06c2dcbcebbf47d","signature":"2e1c22b413f96fd388774b174588816f4bd787486ecfe74f5bcb361dd6bfce50","impliedFormat":99},{"version":"7e771891adaa85b690266bc37bd6eb43bc57eecc4b54693ead36467e7369952a","impliedFormat":1},{"version":"a69c09dbea52352f479d3e7ac949fde3d17b195abe90b045d619f747b38d6d1a","impliedFormat":1},{"version":"f749812878fecfa53cfc13b36e5d35086fb6377983a9df44175da83ccc23af1f","affectsGlobalScope":true,"impliedFormat":1},{"version":"7d2e3fea24c712c99c03ad8f556abedbfe105f87f1be10b95dbd409d24bc05a3","impliedFormat":1},{"version":"211e3f15fbced4ab4be19f49ffa990b9ff20d749d33b65ff753be691e7616239","affectsGlobalScope":true,"impliedFormat":1},{"version":"3719525a8f6ab731e3dfd585d9f87df55ec7d50d461df84f74eb4d68bb165244","impliedFormat":1},{"version":"5a94487653355b56018122d92392beb2e5f4a6c63ba5cef83bbe1c99775ef713","impliedFormat":1},{"version":"d5135ad93b33adcce80b18f8065087934cdc1730d63db58562edcf017e1aad9b","affectsGlobalScope":true,"impliedFormat":1},{"version":"82408ed3e959ddc60d3e9904481b5a8dc16469928257af22a3f7d1a3bc7fd8c4","impliedFormat":1},{"version":"e596c9bb2f29a2699fdd4ae89139612652245192f67f45617c5a4b20832aaae9","impliedFormat":1},{"version":"bb9c4ffa5e6290c6980b63c815cdd1625876dadb2efaf77edbe82984be93e55e","impliedFormat":1},{"version":"1cdcfc1f624d6c08aa12c73935f6e13f095919cd99edf95752951796eb225729","impliedFormat":1},{"version":"4eaff3d8e10676fd7913d8c108890e71c688e1e7d52f6d1d55c39514f493dc47","impliedFormat":1},{"version":"14b5aa23c5d0ae1907bc696ac7b6915d88f7d85799cc0dc2dcf98fbce2c5a67c","impliedFormat":1},{"version":"5c439dafdc09abe4d6c260a96b822fa0ba5be7203c71a63ab1f1423cd9e838ea","impliedFormat":1},{"version":"6b526a5ec4a401ca7c26cfe6a48e641d8f30af76673bad3b06a1b4504594a960","affectsGlobalScope":true,"impliedFormat":1},{"version":"00dee7cdca8b8420c47ea4a31a34b8e8294013ebc4f463fd941e867e7bf05029","affectsGlobalScope":true,"impliedFormat":1},{"version":"3256f3cccd578f9e7fe3a28096c505634bebcee8afb738ffa99368e536ca3a0b","impliedFormat":1},{"version":"1c84b46267610a34028edfd0d035509341751262bac1062857f3c8df7aff7153","impliedFormat":1},{"version":"7f138842074d0a40681775af008c8452093b68c383c94de31759e853c6d06b5c","impliedFormat":1},{"version":"a3d541d303ee505053f5dcbf9fafb65cac3d5631037501cd616195863a6c5740","impliedFormat":1},{"version":"8d3c583a07e0c37e876908c2d5da575019f689df8d9fa4c081d99119d53dba22","impliedFormat":1},{"version":"2c828a5405191d006115ab34e191b8474bc6c86ffdc401d1a9864b1b6e088a58","impliedFormat":1},{"version":"e630e5528e899219ae319e83bef54bf3bcb91b01d76861ecf881e8e614b167f0","affectsGlobalScope":true,"impliedFormat":1},{"version":"bcebb922784739bdb34c18ee51095d25a92b560c78ccd2eaacd6bd00f7443d83","impliedFormat":1},{"version":"7ee6ed878c4528215c82b664fe0cfe80e8b4da6c0d4cc80869367868774db8b1","impliedFormat":1},{"version":"b0973c3cbcdc59b37bf477731d468696ecaf442593ec51bab497a613a580fe30","impliedFormat":1},{"version":"4989e92ba5b69b182d2caaea6295af52b7dc73a4f7a2e336a676722884e7139d","affectsGlobalScope":true,"impliedFormat":1},{"version":"0715e4cd28ad471b2a93f3e552ff51a3ae423417a01a10aa1d3bc7c6b95059d6","affectsGlobalScope":true,"impliedFormat":1},{"version":"5153a2fd150e46ce57bb3f8db1318d33f6ad3261ed70ceeff92281c0608c74a3","impliedFormat":1},{"version":"210d54cd652ec0fec8c8916e4af59bb341065576ecda039842f9ffb2e908507c","impliedFormat":1},{"version":"36b03690b628eab08703d63f04eaa89c5df202e5f1edf3989f13ad389cd2c091","impliedFormat":1},{"version":"0effadd232a20498b11308058e334d3339cc5bf8c4c858393e38d9d4c0013dcf","impliedFormat":1},{"version":"25846d43937c672bab7e8195f3d881f93495df712ee901860effc109918938cc","impliedFormat":1},{"version":"4f3fdeba4e28e21aa719c081b8dc8f91d47e12e773389b9d35679c08151c9d37","impliedFormat":1},{"version":"1b952304137851e45bc009785de89ada562d9376177c97e37702e39e60c2f1ff","impliedFormat":1},{"version":"69ee23dd0d215b09907ad30d23f88b7790c93329d1faf31d7835552a10cf7cbf","impliedFormat":1},{"version":"44b8b584a338b190a59f4f6929d072431950c7bd92ec2694821c11bce180c8a5","impliedFormat":1},{"version":"23b89798789dffbd437c0c423f5d02d11f9736aea73d6abf16db4f812ff36eda","impliedFormat":1},{"version":"f69ff39996a61a0dd10f4bce73272b52e8024a4d58b13ab32bf4712909d0a2b7","impliedFormat":1},{"version":"3c4ba1dd9b12ffa284b565063108f2f031d150ea15b8fafbdc17f5d2a07251f3","affectsGlobalScope":true,"impliedFormat":1},{"version":"e10177274a35a9d07c825615340b2fcde2f610f53f3fb40269fd196b4288dda6","impliedFormat":1},{"version":"1422cd9e705adcc09088fda85a900c2b70e3ad36ea85846f68bd1a884cdf4e2b","impliedFormat":1},{"version":"3c13ef48634e7b5012fcf7e8fce7496352c2d779a7201389ca96a2a81ee4314d","impliedFormat":1},{"version":"5d0a25ec910fa36595f85a67ac992d7a53dd4064a1ba6aea1c9f14ab73a023f2","impliedFormat":1},{"version":"a73ae8c0e62103bb9e21bb6538700881bf135b9a8b125b857ec68edfa0da4ed3","affectsGlobalScope":true,"impliedFormat":1},{"version":"e1c1b2fbe236bf7ee3e342eeae7e20efb8988a0ac7da1cbbfa2c1f66b76c3423","affectsGlobalScope":true,"impliedFormat":1},{"version":"868831cab82b65dfe1d68180e898af1f2101e89ba9b754d1db6fb8cc2fac1921","impliedFormat":1},{"version":"0fe8985a28f82c450a04a6edf1279d7181c0893f37da7d2a27f8efd4fd5edb03","impliedFormat":1},{"version":"e59a892d87e72733e2a9ca21611b9beb52977be2696c7ba4b216cbbb9a48f5aa","impliedFormat":1},{"version":"52120bb7e4583612225bdf08e7c12559548170f11e660d33a33623bae9bbdbba","affectsGlobalScope":true,"impliedFormat":1},{"version":"8a300fa9b698845a1f9c41ecbe2c5966634582a8e2020d51abcace9b55aa959e","impliedFormat":1},{"version":"ab9b9a36e5284fd8d3bf2f7d5fcbc60052f25f27e4d20954782099282c60d23e","affectsGlobalScope":true,"impliedFormat":1},{"version":"a6dd3dba8e665ac43d279e0fdf5219edda0eed69b5e9a5061f46cd6a65c4f7a1","impliedFormat":1}],"root":[61,64,[68,70],[72,74]],"options":{"composite":true,"declarationMap":true,"emitDeclarationOnly":false,"importHelpers":true,"module":199,"noEmitOnError":true,"noFallthroughCasesInSwitch":true,"noImplicitOverride":true,"noImplicitReturns":true,"noUnusedLocals":true,"outDir":"./","rootDir":"../src","skipLibCheck":true,"strict":true,"target":9,"tsBuildInfoFile":"./tsconfig.lib.tsbuildinfo"},"referencedMap":[[65,1],[66,2],[75,3],[76,3],[78,4],[79,5],[80,6],[81,7],[82,8],[83,9],[84,10],[85,11],[86,12],[87,13],[88,13],[90,14],[89,15],[91,14],[92,16],[93,17],[77,18],[127,19],[94,20],[95,21],[96,22],[128,23],[97,24],[98,25],[99,26],[100,27],[101,28],[102,29],[103,30],[104,31],[105,32],[106,33],[107,33],[108,34],[109,35],[111,36],[110,37],[112,38],[113,39],[114,19],[115,40],[116,41],[117,42],[118,43],[119,44],[120,45],[121,46],[122,47],[123,48],[124,49],[125,50],[126,51],[67,19],[71,52],[63,53],[62,19],[60,54],[59,19],[57,19],[58,19],[11,19],[10,19],[2,19],[12,19],[13,19],[14,19],[15,19],[16,19],[17,19],[18,19],[19,19],[3,19],[20,19],[21,19],[4,19],[22,19],[26,19],[23,19],[24,19],[25,19],[27,19],[28,19],[29,19],[5,19],[30,19],[31,19],[32,19],[33,19],[6,19],[37,19],[34,19],[35,19],[36,19],[38,19],[7,19],[39,19],[44,19],[45,19],[40,19],[41,19],[42,19],[43,19],[8,19],[49,19],[46,19],[47,19],[48,19],[50,19],[9,19],[51,19],[52,19],[53,19],[55,19],[54,19],[1,19],[56,19],[61,55],[64,56],[74,57],[68,55],[69,58],[70,59],[73,60],[72,61]],"latestChangedDtsFile":"./prompts.d.ts","version":"5.8.3"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import baseConfig from '../../../../eslint.config.mjs';
|
|
2
|
+
|
|
3
|
+
export default [
|
|
4
|
+
...baseConfig,
|
|
5
|
+
{
|
|
6
|
+
files: ['**/*.json'],
|
|
7
|
+
rules: {
|
|
8
|
+
'@nx/dependency-checks': [
|
|
9
|
+
'error',
|
|
10
|
+
{
|
|
11
|
+
ignoredFiles: ['{projectRoot}/eslint.config.{js,cjs,mjs,ts,cts,mts}'],
|
|
12
|
+
},
|
|
13
|
+
],
|
|
14
|
+
},
|
|
15
|
+
languageOptions: {
|
|
16
|
+
parser: await import('jsonc-eslint-parser'),
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
];
|
package/package.json
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@react-native-harness/tools",
|
|
3
|
+
"version": "1.0.0-alpha.1",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"module": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
"./package.json": "./package.json",
|
|
10
|
+
".": {
|
|
11
|
+
"development": "./src/index.ts",
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"import": "./dist/index.js",
|
|
14
|
+
"default": "./dist/index.js"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"dependencies": {
|
|
18
|
+
"@clack/prompts": "alpha",
|
|
19
|
+
"nano-spawn": "^1.0.2",
|
|
20
|
+
"picocolors": "^1.1.1",
|
|
21
|
+
"tslib": "^2.3.0"
|
|
22
|
+
}
|
|
23
|
+
}
|
package/src/abort.ts
ADDED
package/src/color.ts
ADDED
package/src/index.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Source from https://github.com/sindresorhus/is-interactive/blob/main/index.js
|
|
3
|
+
*/
|
|
4
|
+
export const isInteractive = ({ stream = process.stdout } = {}) => {
|
|
5
|
+
return Boolean(
|
|
6
|
+
stream &&
|
|
7
|
+
stream.isTTY &&
|
|
8
|
+
process.env['TERM'] !== 'dumb' &&
|
|
9
|
+
!('CI' in process.env)
|
|
10
|
+
);
|
|
11
|
+
};
|
package/src/logger.ts
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import util from 'node:util';
|
|
2
|
+
import { log as clackLog } from '@clack/prompts';
|
|
3
|
+
import isUnicodeSupported from 'is-unicode-supported';
|
|
4
|
+
import { color } from './color.js';
|
|
5
|
+
import { isInteractive } from './isInteractive.js';
|
|
6
|
+
|
|
7
|
+
const unicode = isUnicodeSupported();
|
|
8
|
+
|
|
9
|
+
const unicodeWithFallback = (c: string, fallback: string) =>
|
|
10
|
+
unicode ? c : fallback;
|
|
11
|
+
|
|
12
|
+
const SYMBOL_DEBUG = unicodeWithFallback('●', '•');
|
|
13
|
+
|
|
14
|
+
let verbose = false;
|
|
15
|
+
|
|
16
|
+
const success = (...messages: Array<unknown>) => {
|
|
17
|
+
const output = util.format(...messages);
|
|
18
|
+
clackLog.success(output);
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const info = (...messages: Array<unknown>) => {
|
|
22
|
+
const output = util.format(...messages);
|
|
23
|
+
clackLog.info(output);
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const warn = (...messages: Array<unknown>) => {
|
|
27
|
+
const output = util.format(...messages);
|
|
28
|
+
clackLog.warn(mapLines(output, color.yellow));
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const error = (...messages: Array<unknown>) => {
|
|
32
|
+
const output = util.format(...messages);
|
|
33
|
+
clackLog.error(mapLines(output, color.red));
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
const log = (...messages: Array<unknown>) => {
|
|
37
|
+
const output = util.format(...messages);
|
|
38
|
+
clackLog.step(output);
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
const debug = (...messages: Array<unknown>) => {
|
|
42
|
+
if (verbose) {
|
|
43
|
+
const output = util.format(...messages);
|
|
44
|
+
clackLog.message(mapLines(output, color.dim), {
|
|
45
|
+
symbol: color.dim(SYMBOL_DEBUG),
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
const setVerbose = (level: boolean) => {
|
|
51
|
+
verbose = level;
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
const isVerbose = () => {
|
|
55
|
+
// For non-interactive environments, always show verbose logs
|
|
56
|
+
return !isInteractive() || verbose;
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
export const logger = {
|
|
60
|
+
success,
|
|
61
|
+
info,
|
|
62
|
+
warn,
|
|
63
|
+
error,
|
|
64
|
+
debug,
|
|
65
|
+
log,
|
|
66
|
+
setVerbose,
|
|
67
|
+
isVerbose,
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
function mapLines(text: string, colorFn: (line: string) => string) {
|
|
71
|
+
return text.split('\n').map(colorFn).join('\n');
|
|
72
|
+
}
|
package/src/prompts.ts
ADDED
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import * as clack from '@clack/prompts';
|
|
2
|
+
import { isInteractive } from './isInteractive.js';
|
|
3
|
+
import { logger } from './logger.js';
|
|
4
|
+
|
|
5
|
+
export const intro = (title?: string) => clack.intro(title);
|
|
6
|
+
|
|
7
|
+
export const outro = (message?: string) => clack.outro(message);
|
|
8
|
+
|
|
9
|
+
export const note = (message?: string, title?: string) =>
|
|
10
|
+
clack.note(message, title);
|
|
11
|
+
|
|
12
|
+
export const promptText = async (
|
|
13
|
+
options: clack.TextOptions
|
|
14
|
+
): Promise<string> => {
|
|
15
|
+
const result = await clack.text(options);
|
|
16
|
+
if (clack.isCancel(result)) {
|
|
17
|
+
cancelPromptAndExit();
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return result as string;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export const promptPassword = async (
|
|
24
|
+
options: clack.PasswordOptions
|
|
25
|
+
): Promise<string> => {
|
|
26
|
+
const result = await clack.password(options);
|
|
27
|
+
if (clack.isCancel(result)) {
|
|
28
|
+
cancelPromptAndExit();
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return result as string;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export const promptSelect = async <T>(
|
|
35
|
+
options: clack.SelectOptions<T>
|
|
36
|
+
): Promise<T> => {
|
|
37
|
+
// If there is only one option, return it immediately
|
|
38
|
+
if (options.options.length === 1) {
|
|
39
|
+
return options.options[0].value as T;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const result = await clack.select<T>(options);
|
|
43
|
+
if (clack.isCancel(result)) {
|
|
44
|
+
cancelPromptAndExit();
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return result as T;
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
type ConfirmOptions = {
|
|
51
|
+
message: string;
|
|
52
|
+
confirmLabel?: string;
|
|
53
|
+
cancelLabel?: string;
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
export const promptConfirm = async (
|
|
57
|
+
options: ConfirmOptions
|
|
58
|
+
): Promise<boolean> => {
|
|
59
|
+
const result = await clack.select({
|
|
60
|
+
message: options.message,
|
|
61
|
+
options: [
|
|
62
|
+
{ value: true, label: options.confirmLabel ?? 'Confirm' },
|
|
63
|
+
{ value: false, label: options.cancelLabel ?? 'Cancel' },
|
|
64
|
+
],
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
if (clack.isCancel(result)) {
|
|
68
|
+
cancelPromptAndExit();
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return result === true;
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
export const promptMultiselect = async <T>(
|
|
75
|
+
options: clack.MultiSelectOptions<T>
|
|
76
|
+
): Promise<T[]> => {
|
|
77
|
+
const result = await clack.multiselect<T>(options);
|
|
78
|
+
if (clack.isCancel(result)) {
|
|
79
|
+
cancelPromptAndExit();
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return result as T[];
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
export const promptGroup = async <T>(
|
|
86
|
+
prompts: clack.PromptGroup<T>,
|
|
87
|
+
options?: clack.PromptGroupOptions<T> | undefined
|
|
88
|
+
): Promise<T> => {
|
|
89
|
+
const result = await clack.group(prompts, options);
|
|
90
|
+
if (clack.isCancel(result)) {
|
|
91
|
+
cancelPromptAndExit();
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return result;
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
export const spinner = (options?: clack.SpinnerOptions) => {
|
|
98
|
+
if (logger.isVerbose() || !isInteractive()) {
|
|
99
|
+
return {
|
|
100
|
+
start: (message?: string) => logger.log(formatStartMessage(message)),
|
|
101
|
+
stop: (message?: string, code = 0) => {
|
|
102
|
+
return code === 0 ? logger.log(message) : logger.error(message);
|
|
103
|
+
},
|
|
104
|
+
message: (message?: string) => logger.log(formatStartMessage(message)),
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const clackSpinner = clack.spinner(options);
|
|
109
|
+
|
|
110
|
+
return {
|
|
111
|
+
start: (message?: string) => {
|
|
112
|
+
clackSpinner.start(message);
|
|
113
|
+
},
|
|
114
|
+
stop: (message?: string, code?: number) => {
|
|
115
|
+
clackSpinner.stop(message, code);
|
|
116
|
+
},
|
|
117
|
+
message: (message?: string) => {
|
|
118
|
+
clackSpinner.message(message);
|
|
119
|
+
},
|
|
120
|
+
};
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
export const progress = (options?: clack.ProgressOptions) => {
|
|
124
|
+
if (logger.isVerbose() || !isInteractive()) {
|
|
125
|
+
return {
|
|
126
|
+
start: (message?: string) => logger.log(formatStartMessage(message)),
|
|
127
|
+
advance: (_: number, message?: string) => {
|
|
128
|
+
logger.log(formatStartMessage(message));
|
|
129
|
+
},
|
|
130
|
+
stop: (message?: string, code = 0) => {
|
|
131
|
+
return code === 0 ? logger.log(message) : logger.error(message);
|
|
132
|
+
},
|
|
133
|
+
message: (message?: string) => logger.log(formatStartMessage(message)),
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const clackProgress = clack.progress(options);
|
|
138
|
+
|
|
139
|
+
return {
|
|
140
|
+
start: (message?: string) => {
|
|
141
|
+
clackProgress.start(message);
|
|
142
|
+
},
|
|
143
|
+
advance: (value: number, message?: string) => {
|
|
144
|
+
clackProgress.advance(value, message);
|
|
145
|
+
},
|
|
146
|
+
stop: (message?: string, code = 0) => {
|
|
147
|
+
clackProgress.stop(message, code);
|
|
148
|
+
},
|
|
149
|
+
message: (message?: string) => {
|
|
150
|
+
clackProgress.message(message);
|
|
151
|
+
},
|
|
152
|
+
};
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
export const formatStartMessage = (
|
|
156
|
+
text: string | undefined
|
|
157
|
+
): string | undefined => {
|
|
158
|
+
if (text === undefined) {
|
|
159
|
+
return undefined;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
const messageWithoutDots = text.replace(/\.+$/, '');
|
|
163
|
+
return `${messageWithoutDots}...`;
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
export const cancelPromptAndExit = (message?: string): never => {
|
|
167
|
+
clack.cancel(message ?? 'Operation cancelled by user.');
|
|
168
|
+
process.exit(0);
|
|
169
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { createRequire } from 'node:module';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import fs from 'node:fs';
|
|
4
|
+
|
|
5
|
+
export const getReactNativePackagePath = (): string => {
|
|
6
|
+
const require = createRequire(import.meta.url);
|
|
7
|
+
const input = require.resolve('react-native', { paths: [process.cwd()] });
|
|
8
|
+
return path.dirname(input);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export const getReactNativeCliPath = (): string => {
|
|
12
|
+
const reactNativePackagePath = getReactNativePackagePath();
|
|
13
|
+
const packageJson = JSON.parse(fs.readFileSync(path.join(reactNativePackagePath, 'package.json'), 'utf8'));
|
|
14
|
+
return path.join(reactNativePackagePath, packageJson.bin['react-native']);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export const getExpoPackagePath = (): string => {
|
|
18
|
+
const require = createRequire(import.meta.url);
|
|
19
|
+
const input = require.resolve('expo', { paths: [process.cwd()] });
|
|
20
|
+
return path.join(path.dirname(input), '..');
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export const getExpoCliPath = (): string => {
|
|
24
|
+
const expoPackagePath = getExpoPackagePath();
|
|
25
|
+
const packageJson = JSON.parse(fs.readFileSync(path.join(expoPackagePath, 'package.json'), 'utf8'));
|
|
26
|
+
return path.join(expoPackagePath, packageJson.bin['expo']);
|
|
27
|
+
}
|
package/src/spawn.ts
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import type { Options, Subprocess } from 'nano-spawn';
|
|
2
|
+
import nanoSpawn, { SubprocessError } from 'nano-spawn';
|
|
3
|
+
import { logger } from './logger.js';
|
|
4
|
+
|
|
5
|
+
export type SpawnOptions = Options;
|
|
6
|
+
|
|
7
|
+
export const spawn = (
|
|
8
|
+
file: string,
|
|
9
|
+
args?: readonly string[],
|
|
10
|
+
options?: SpawnOptions
|
|
11
|
+
): Subprocess => {
|
|
12
|
+
const defaultStream = 'pipe';
|
|
13
|
+
const defaultOptions: Options = {
|
|
14
|
+
stdin: defaultStream,
|
|
15
|
+
stdout: defaultStream,
|
|
16
|
+
// Always 'pipe' stderr to handle errors properly down the line
|
|
17
|
+
stderr: 'pipe',
|
|
18
|
+
};
|
|
19
|
+
logger.debug(`Running: ${file}`, ...(args ?? []));
|
|
20
|
+
const childProcess = nanoSpawn(file, args, { ...defaultOptions, ...options });
|
|
21
|
+
|
|
22
|
+
setupChildProcessCleanup(childProcess);
|
|
23
|
+
return childProcess;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export const spawnAndForget = async (file: string, args?: readonly string[], options?: SpawnOptions): Promise<void> => {
|
|
27
|
+
try {
|
|
28
|
+
await spawn(file, args, options);
|
|
29
|
+
} catch {
|
|
30
|
+
// We don't care about the error here.
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export { Subprocess, SubprocessError };
|
|
35
|
+
|
|
36
|
+
const setupChildProcessCleanup = (childProcess: Subprocess) => {
|
|
37
|
+
// https://stackoverflow.com/questions/53049939/node-daemon-wont-start-with-process-stdin-setrawmodetrue/53050098#53050098
|
|
38
|
+
if (process.stdin.isTTY) {
|
|
39
|
+
// overwrite @clack/prompts setting raw mode for spinner and prompts,
|
|
40
|
+
// which prevents listening for SIGINT and SIGTERM
|
|
41
|
+
process.stdin.setRawMode(false);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const terminate = async () => {
|
|
45
|
+
try {
|
|
46
|
+
(await childProcess.nodeChildProcess).kill();
|
|
47
|
+
process.exit(1);
|
|
48
|
+
} catch {
|
|
49
|
+
// ignore
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
const sigintHandler = () => terminate();
|
|
54
|
+
const sigtermHandler = () => terminate();
|
|
55
|
+
|
|
56
|
+
process.on('SIGINT', sigintHandler);
|
|
57
|
+
process.on('SIGTERM', sigtermHandler);
|
|
58
|
+
|
|
59
|
+
const cleanup = () => {
|
|
60
|
+
process.off('SIGINT', sigintHandler);
|
|
61
|
+
process.off('SIGTERM', sigtermHandler);
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
childProcess.nodeChildProcess.finally(cleanup);
|
|
65
|
+
};
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"extends": "../../tsconfig.base.json",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"baseUrl": ".",
|
|
5
|
+
"rootDir": "src",
|
|
6
|
+
"outDir": "dist",
|
|
7
|
+
"tsBuildInfoFile": "dist/tsconfig.lib.tsbuildinfo",
|
|
8
|
+
"emitDeclarationOnly": false,
|
|
9
|
+
"forceConsistentCasingInFileNames": true,
|
|
10
|
+
"types": ["node"]
|
|
11
|
+
},
|
|
12
|
+
"include": ["src/**/*.ts"],
|
|
13
|
+
"references": []
|
|
14
|
+
}
|