appium 3.2.2 → 3.3.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.
Files changed (250) hide show
  1. package/build/lib/appium.d.ts +147 -205
  2. package/build/lib/appium.d.ts.map +1 -1
  3. package/build/lib/appium.js +169 -282
  4. package/build/lib/appium.js.map +1 -1
  5. package/build/lib/bidi-commands.d.ts.map +1 -1
  6. package/build/lib/bidi-commands.js +11 -11
  7. package/build/lib/bidi-commands.js.map +1 -1
  8. package/build/lib/bootstrap/appium-initializer.d.ts +21 -0
  9. package/build/lib/bootstrap/appium-initializer.d.ts.map +1 -0
  10. package/build/lib/bootstrap/appium-initializer.js +146 -0
  11. package/build/lib/bootstrap/appium-initializer.js.map +1 -0
  12. package/build/lib/bootstrap/appium-main-runner.d.ts +22 -0
  13. package/build/lib/bootstrap/appium-main-runner.d.ts.map +1 -0
  14. package/build/lib/bootstrap/appium-main-runner.js +109 -0
  15. package/build/lib/bootstrap/appium-main-runner.js.map +1 -0
  16. package/build/lib/bootstrap/config-file.d.ts +37 -0
  17. package/build/lib/bootstrap/config-file.d.ts.map +1 -0
  18. package/build/lib/{config-file.js → bootstrap/config-file.js} +62 -138
  19. package/build/lib/bootstrap/config-file.js.map +1 -0
  20. package/build/lib/bootstrap/grid-v3-register.d.ts +20 -0
  21. package/build/lib/bootstrap/grid-v3-register.d.ts.map +1 -0
  22. package/build/lib/bootstrap/grid-v3-register.js +185 -0
  23. package/build/lib/bootstrap/grid-v3-register.js.map +1 -0
  24. package/build/lib/bootstrap/init-types.d.ts +16 -0
  25. package/build/lib/bootstrap/init-types.d.ts.map +1 -0
  26. package/build/lib/bootstrap/init-types.js +3 -0
  27. package/build/lib/bootstrap/init-types.js.map +1 -0
  28. package/build/lib/bootstrap/main-helpers.d.ts +55 -0
  29. package/build/lib/bootstrap/main-helpers.d.ts.map +1 -0
  30. package/build/lib/bootstrap/main-helpers.js +187 -0
  31. package/build/lib/bootstrap/main-helpers.js.map +1 -0
  32. package/build/lib/bootstrap/node-helpers.d.ts +32 -0
  33. package/build/lib/bootstrap/node-helpers.d.ts.map +1 -0
  34. package/build/lib/bootstrap/node-helpers.js +201 -0
  35. package/build/lib/bootstrap/node-helpers.js.map +1 -0
  36. package/build/lib/bootstrap/startup-config.d.ts +22 -0
  37. package/build/lib/bootstrap/startup-config.d.ts.map +1 -0
  38. package/build/lib/bootstrap/startup-config.js +111 -0
  39. package/build/lib/bootstrap/startup-config.js.map +1 -0
  40. package/build/lib/cli/args.d.ts +16 -12
  41. package/build/lib/cli/args.d.ts.map +1 -1
  42. package/build/lib/cli/args.js +20 -40
  43. package/build/lib/cli/args.js.map +1 -1
  44. package/build/lib/cli/driver-command.d.ts +51 -93
  45. package/build/lib/cli/driver-command.d.ts.map +1 -1
  46. package/build/lib/cli/driver-command.js +11 -66
  47. package/build/lib/cli/driver-command.js.map +1 -1
  48. package/build/lib/cli/extension-command.d.ts +173 -377
  49. package/build/lib/cli/extension-command.d.ts.map +1 -1
  50. package/build/lib/cli/extension-command.js +387 -656
  51. package/build/lib/cli/extension-command.js.map +1 -1
  52. package/build/lib/cli/extension.d.ts +10 -15
  53. package/build/lib/cli/extension.d.ts.map +1 -1
  54. package/build/lib/cli/extension.js +15 -33
  55. package/build/lib/cli/extension.js.map +1 -1
  56. package/build/lib/cli/parser.d.ts +37 -66
  57. package/build/lib/cli/parser.d.ts.map +1 -1
  58. package/build/lib/cli/parser.js +69 -104
  59. package/build/lib/cli/parser.js.map +1 -1
  60. package/build/lib/cli/plugin-command.d.ts +50 -90
  61. package/build/lib/cli/plugin-command.d.ts.map +1 -1
  62. package/build/lib/cli/plugin-command.js +11 -63
  63. package/build/lib/cli/plugin-command.js.map +1 -1
  64. package/build/lib/cli/setup-command.d.ts +21 -26
  65. package/build/lib/cli/setup-command.d.ts.map +1 -1
  66. package/build/lib/cli/setup-command.js +19 -61
  67. package/build/lib/cli/setup-command.js.map +1 -1
  68. package/build/lib/cli/utils.d.ts +33 -35
  69. package/build/lib/cli/utils.d.ts.map +1 -1
  70. package/build/lib/cli/utils.js +48 -50
  71. package/build/lib/cli/utils.js.map +1 -1
  72. package/build/lib/constants.d.ts +23 -23
  73. package/build/lib/constants.d.ts.map +1 -1
  74. package/build/lib/constants.js +10 -15
  75. package/build/lib/constants.js.map +1 -1
  76. package/build/lib/doctor/doctor.d.ts +40 -57
  77. package/build/lib/doctor/doctor.d.ts.map +1 -1
  78. package/build/lib/doctor/doctor.js +31 -62
  79. package/build/lib/doctor/doctor.js.map +1 -1
  80. package/build/lib/extension/driver-config.d.ts +18 -77
  81. package/build/lib/extension/driver-config.d.ts.map +1 -1
  82. package/build/lib/extension/driver-config.js +37 -125
  83. package/build/lib/extension/driver-config.js.map +1 -1
  84. package/build/lib/extension/extension-config.d.ts +103 -210
  85. package/build/lib/extension/extension-config.d.ts.map +1 -1
  86. package/build/lib/extension/extension-config.js +180 -342
  87. package/build/lib/extension/extension-config.js.map +1 -1
  88. package/build/lib/extension/index.d.ts +12 -29
  89. package/build/lib/extension/index.d.ts.map +1 -1
  90. package/build/lib/extension/index.js +33 -75
  91. package/build/lib/extension/index.js.map +1 -1
  92. package/build/lib/extension/manifest-migrations.d.ts +3 -20
  93. package/build/lib/extension/manifest-migrations.d.ts.map +1 -1
  94. package/build/lib/extension/manifest-migrations.js +20 -101
  95. package/build/lib/extension/manifest-migrations.js.map +1 -1
  96. package/build/lib/extension/manifest.d.ts +61 -107
  97. package/build/lib/extension/manifest.d.ts.map +1 -1
  98. package/build/lib/extension/manifest.js +181 -356
  99. package/build/lib/extension/manifest.js.map +1 -1
  100. package/build/lib/extension/package-changed.d.ts +1 -3
  101. package/build/lib/extension/package-changed.d.ts.map +1 -1
  102. package/build/lib/extension/package-changed.js +8 -15
  103. package/build/lib/extension/package-changed.js.map +1 -1
  104. package/build/lib/extension/plugin-config.d.ts +10 -52
  105. package/build/lib/extension/plugin-config.d.ts.map +1 -1
  106. package/build/lib/extension/plugin-config.js +11 -63
  107. package/build/lib/extension/plugin-config.js.map +1 -1
  108. package/build/lib/helpers/build.d.ts +22 -0
  109. package/build/lib/helpers/build.d.ts.map +1 -0
  110. package/build/lib/helpers/build.js +109 -0
  111. package/build/lib/helpers/build.js.map +1 -0
  112. package/build/lib/helpers/capability.d.ts +38 -0
  113. package/build/lib/helpers/capability.d.ts.map +1 -0
  114. package/build/lib/helpers/capability.js +128 -0
  115. package/build/lib/helpers/capability.js.map +1 -0
  116. package/build/lib/helpers/network.d.ts +14 -0
  117. package/build/lib/helpers/network.d.ts.map +1 -0
  118. package/build/lib/helpers/network.js +35 -0
  119. package/build/lib/helpers/network.js.map +1 -0
  120. package/build/lib/insecure-features.js +6 -6
  121. package/build/lib/insecure-features.js.map +1 -1
  122. package/build/lib/inspector-commands.d.ts +6 -0
  123. package/build/lib/inspector-commands.d.ts.map +1 -1
  124. package/build/lib/inspector-commands.js +6 -0
  125. package/build/lib/inspector-commands.js.map +1 -1
  126. package/build/lib/logger.d.ts +2 -3
  127. package/build/lib/logger.d.ts.map +1 -1
  128. package/build/lib/logger.js +2 -3
  129. package/build/lib/logger.js.map +1 -1
  130. package/build/lib/logsink.d.ts +13 -22
  131. package/build/lib/logsink.d.ts.map +1 -1
  132. package/build/lib/logsink.js +48 -103
  133. package/build/lib/logsink.js.map +1 -1
  134. package/build/lib/main.d.ts +15 -58
  135. package/build/lib/main.d.ts.map +1 -1
  136. package/build/lib/main.js +25 -425
  137. package/build/lib/main.js.map +1 -1
  138. package/build/lib/schema/arg-spec.d.ts +32 -107
  139. package/build/lib/schema/arg-spec.d.ts.map +1 -1
  140. package/build/lib/schema/arg-spec.js +11 -107
  141. package/build/lib/schema/arg-spec.js.map +1 -1
  142. package/build/lib/schema/cli-args-guards.d.ts +34 -0
  143. package/build/lib/schema/cli-args-guards.d.ts.map +1 -0
  144. package/build/lib/schema/cli-args-guards.js +49 -0
  145. package/build/lib/schema/cli-args-guards.js.map +1 -0
  146. package/build/lib/schema/cli-args.d.ts +3 -15
  147. package/build/lib/schema/cli-args.d.ts.map +1 -1
  148. package/build/lib/schema/cli-args.js +17 -107
  149. package/build/lib/schema/cli-args.js.map +1 -1
  150. package/build/lib/schema/cli-transformers.d.ts +15 -12
  151. package/build/lib/schema/cli-transformers.d.ts.map +1 -1
  152. package/build/lib/schema/cli-transformers.js +15 -45
  153. package/build/lib/schema/cli-transformers.js.map +1 -1
  154. package/build/lib/schema/format-errors.d.ts +28 -0
  155. package/build/lib/schema/format-errors.d.ts.map +1 -0
  156. package/build/lib/schema/format-errors.js +29 -0
  157. package/build/lib/schema/format-errors.js.map +1 -0
  158. package/build/lib/schema/index.d.ts +4 -2
  159. package/build/lib/schema/index.d.ts.map +1 -1
  160. package/build/lib/schema/index.js +2 -0
  161. package/build/lib/schema/index.js.map +1 -1
  162. package/build/lib/schema/keywords.d.ts +12 -20
  163. package/build/lib/schema/keywords.d.ts.map +1 -1
  164. package/build/lib/schema/keywords.js +6 -51
  165. package/build/lib/schema/keywords.js.map +1 -1
  166. package/build/lib/schema/schema.d.ts +106 -231
  167. package/build/lib/schema/schema.d.ts.map +1 -1
  168. package/build/lib/schema/schema.js +88 -358
  169. package/build/lib/schema/schema.js.map +1 -1
  170. package/build/lib/utils.d.ts +7 -267
  171. package/build/lib/utils.d.ts.map +1 -1
  172. package/build/lib/utils.js +10 -409
  173. package/build/lib/utils.js.map +1 -1
  174. package/lib/{appium.js → appium.ts} +297 -341
  175. package/lib/bidi-commands.ts +10 -14
  176. package/lib/bootstrap/appium-initializer.ts +212 -0
  177. package/lib/bootstrap/appium-main-runner.ts +172 -0
  178. package/lib/bootstrap/config-file.ts +178 -0
  179. package/lib/bootstrap/grid-v3-register.ts +250 -0
  180. package/lib/bootstrap/init-types.ts +31 -0
  181. package/lib/bootstrap/main-helpers.ts +223 -0
  182. package/lib/bootstrap/node-helpers.ts +180 -0
  183. package/lib/bootstrap/startup-config.ts +143 -0
  184. package/lib/cli/{args.js → args.ts} +45 -56
  185. package/lib/cli/driver-command.ts +122 -0
  186. package/lib/cli/{extension-command.js → extension-command.ts} +827 -906
  187. package/lib/cli/extension.ts +65 -0
  188. package/lib/cli/{parser.js → parser.ts} +93 -116
  189. package/lib/cli/plugin-command.ts +117 -0
  190. package/lib/cli/{setup-command.js → setup-command.ts} +59 -74
  191. package/lib/cli/utils.ts +97 -0
  192. package/lib/{constants.js → constants.ts} +30 -41
  193. package/lib/doctor/{doctor.js → doctor.ts} +82 -92
  194. package/lib/extension/driver-config.ts +165 -0
  195. package/lib/extension/{extension-config.js → extension-config.ts} +291 -405
  196. package/lib/extension/index.ts +143 -0
  197. package/lib/extension/manifest-migrations.ts +57 -0
  198. package/lib/extension/manifest.ts +369 -0
  199. package/lib/extension/{package-changed.js → package-changed.ts} +9 -18
  200. package/lib/extension/plugin-config.ts +62 -0
  201. package/lib/helpers/build.ts +111 -0
  202. package/lib/helpers/capability.ts +171 -0
  203. package/lib/helpers/network.ts +30 -0
  204. package/lib/insecure-features.ts +1 -1
  205. package/lib/inspector-commands.ts +6 -1
  206. package/lib/{logger.js → logger.ts} +1 -2
  207. package/lib/{logsink.js → logsink.ts} +91 -137
  208. package/lib/main.ts +60 -0
  209. package/lib/schema/arg-spec.ts +131 -0
  210. package/lib/schema/cli-args-guards.ts +67 -0
  211. package/lib/schema/cli-args.ts +171 -0
  212. package/lib/schema/cli-transformers.ts +83 -0
  213. package/lib/schema/format-errors.ts +43 -0
  214. package/lib/schema/index.ts +4 -0
  215. package/lib/schema/keywords.ts +96 -0
  216. package/lib/schema/schema.ts +448 -0
  217. package/lib/utils.ts +73 -0
  218. package/package.json +17 -18
  219. package/scripts/autoinstall-extensions.js +3 -0
  220. package/build/lib/config-file.d.ts +0 -100
  221. package/build/lib/config-file.d.ts.map +0 -1
  222. package/build/lib/config-file.js.map +0 -1
  223. package/build/lib/config.d.ts +0 -70
  224. package/build/lib/config.d.ts.map +0 -1
  225. package/build/lib/config.js +0 -390
  226. package/build/lib/config.js.map +0 -1
  227. package/build/lib/grid-register.d.ts +0 -10
  228. package/build/lib/grid-register.d.ts.map +0 -1
  229. package/build/lib/grid-register.js +0 -134
  230. package/build/lib/grid-register.js.map +0 -1
  231. package/lib/cli/driver-command.js +0 -174
  232. package/lib/cli/extension.js +0 -74
  233. package/lib/cli/plugin-command.js +0 -164
  234. package/lib/cli/utils.js +0 -91
  235. package/lib/config-file.js +0 -228
  236. package/lib/config.js +0 -389
  237. package/lib/extension/driver-config.js +0 -245
  238. package/lib/extension/index.js +0 -169
  239. package/lib/extension/manifest-migrations.js +0 -136
  240. package/lib/extension/manifest.js +0 -550
  241. package/lib/extension/plugin-config.js +0 -112
  242. package/lib/grid-register.js +0 -146
  243. package/lib/main.js +0 -545
  244. package/lib/schema/arg-spec.js +0 -229
  245. package/lib/schema/cli-args.js +0 -254
  246. package/lib/schema/cli-transformers.js +0 -113
  247. package/lib/schema/index.js +0 -2
  248. package/lib/schema/keywords.js +0 -136
  249. package/lib/schema/schema.js +0 -725
  250. package/lib/utils.js +0 -512
@@ -0,0 +1,171 @@
1
+ import {ArgumentTypeError, type ArgumentOptions} from 'argparse';
2
+ import _ from 'lodash';
3
+ import type {JSONSchema7, JSONSchema7TypeName} from 'json-schema';
4
+ import {formatErrors} from './format-errors';
5
+ import {flattenSchema, validate} from './schema';
6
+ import {transformers, parseCsvLine} from './cli-transformers';
7
+ import type {ArgSpec} from './arg-spec';
8
+ import type {AppiumJSONSchemaKeywords, AppiumCliTransformerName} from './keywords';
9
+ import type {ArgumentDefinitions} from '../cli/args';
10
+
11
+ type AppiumJSONSchema = AppiumJSONSchemaKeywords & JSONSchema7;
12
+ type ArgDef = [[string] | [string, string], ArgumentOptions];
13
+
14
+ const TYPENAMES: Readonly<Record<string, JSONSchema7TypeName>> = Object.freeze({
15
+ ARRAY: 'array',
16
+ OBJECT: 'object',
17
+ BOOLEAN: 'boolean',
18
+ INTEGER: 'integer',
19
+ NUMBER: 'number',
20
+ NULL: 'null',
21
+ STRING: 'string',
22
+ });
23
+
24
+ const SHORT_ARG_CUTOFF = 3;
25
+
26
+ /**
27
+ * Converts the finalized, flattened schema representation into
28
+ * `ArgumentDefinitions` for handoff to `argparse`.
29
+ */
30
+ export function toParserArgs(): ArgumentDefinitions {
31
+ const flattened = flattenSchema().filter(({schema}) => !schema.appiumCliIgnored);
32
+ return new Map(
33
+ _.map(flattened, ({schema, argSpec}) => subSchemaToArgDef(schema as AppiumJSONSchema, argSpec))
34
+ );
35
+ }
36
+
37
+ /**
38
+ * Convert an alias (`foo`) to a flag (`--foo`) or short flag (`-f`).
39
+ */
40
+ function aliasToFlag(argSpec: ArgSpec, alias?: string): string {
41
+ const {extType, extName, name} = argSpec;
42
+ const arg = alias ?? name;
43
+ const isShort = arg.length < SHORT_ARG_CUTOFF;
44
+ if (extType && extName) {
45
+ return isShort
46
+ ? `--${extType}-${_.kebabCase(extName)}-${arg}`
47
+ : `--${extType}-${_.kebabCase(extName)}-${_.kebabCase(arg)}`;
48
+ }
49
+ return isShort ? `-${arg}` : `--${_.kebabCase(arg)}`;
50
+ }
51
+
52
+ const screamingSnakeCase = _.flow(_.snakeCase, _.toUpper);
53
+
54
+ /**
55
+ * Given an argument spec, return a validator/coercer function backed by schema validation.
56
+ */
57
+ function getSchemaValidator<Coerced>(
58
+ {ref: schemaId}: ArgSpec,
59
+ coerce: (value: string) => Coerced = _.identity as (value: string) => Coerced
60
+ ): (value: string) => Coerced {
61
+ return (value) => {
62
+ const coerced = coerce(value);
63
+ const errors = validate(coerced, schemaId);
64
+ if (_.isEmpty(errors)) {
65
+ return coerced;
66
+ }
67
+ throw new ArgumentTypeError('\n\n' + formatErrors(errors, value, {schemaId}));
68
+ };
69
+ }
70
+
71
+ function makeDescription(schema: AppiumJSONSchema): string {
72
+ const {appiumCliDescription, description = '', appiumDeprecated} = schema;
73
+ let desc = appiumCliDescription ?? description;
74
+ if (appiumDeprecated) {
75
+ desc = `[DEPRECATED] ${desc}`;
76
+ }
77
+ return desc;
78
+ }
79
+
80
+ function subSchemaToArgDef(subSchema: AppiumJSONSchema, argSpec: ArgSpec): ArgDef {
81
+ const {type, appiumCliAliases, appiumCliTransformer, enum: enumValues} = subSchema;
82
+ const {name, arg} = argSpec;
83
+
84
+ const aliases = [
85
+ aliasToFlag(argSpec),
86
+ ...((appiumCliAliases ?? []) as string[]).map((alias) => aliasToFlag(argSpec, alias)),
87
+ ];
88
+
89
+ const argOpts: ArgumentOptions = {
90
+ required: false,
91
+ help: makeDescription(subSchema),
92
+ };
93
+
94
+ if (!argSpec.extType) {
95
+ argOpts.dest = argSpec.rawDest;
96
+ }
97
+
98
+ let argTypeFunction: ((value: string) => unknown) | undefined;
99
+
100
+ switch (type) {
101
+ case TYPENAMES.BOOLEAN: {
102
+ argOpts.action = 'store_const';
103
+ argOpts.const = true;
104
+ break;
105
+ }
106
+ case TYPENAMES.OBJECT: {
107
+ argTypeFunction = _.flow(transformers.json, (o) => {
108
+ if (!_.isPlainObject(o)) {
109
+ throw new ArgumentTypeError(`'${_.truncate(String(o), {length: 100})}' must be a plain object`);
110
+ }
111
+ return o;
112
+ });
113
+ break;
114
+ }
115
+ case TYPENAMES.ARRAY: {
116
+ argTypeFunction = parseCsvLine;
117
+ break;
118
+ }
119
+ case TYPENAMES.NUMBER: {
120
+ argTypeFunction = getSchemaValidator(argSpec, parseFloat);
121
+ break;
122
+ }
123
+ case TYPENAMES.INTEGER: {
124
+ argTypeFunction = getSchemaValidator(argSpec, _.parseInt);
125
+ break;
126
+ }
127
+ case TYPENAMES.STRING: {
128
+ argTypeFunction = getSchemaValidator(argSpec);
129
+ break;
130
+ }
131
+ case TYPENAMES.NULL:
132
+ default: {
133
+ throw new TypeError(`Schema property "${arg}": \`${type}\` type unknown or disallowed`);
134
+ }
135
+ }
136
+
137
+ if (type !== TYPENAMES.BOOLEAN) {
138
+ argOpts.metavar = screamingSnakeCase(name);
139
+ }
140
+
141
+ if (appiumCliTransformer && transformers[appiumCliTransformer as AppiumCliTransformerName]) {
142
+ if (type === TYPENAMES.ARRAY) {
143
+ const csvTransformer = argTypeFunction as (x: string) => string[];
144
+ argTypeFunction = (val) =>
145
+ _.flatMap(csvTransformer(val).map(transformers[appiumCliTransformer as AppiumCliTransformerName]));
146
+ } else {
147
+ argTypeFunction = _.flow(
148
+ argTypeFunction ?? _.identity,
149
+ transformers[appiumCliTransformer as AppiumCliTransformerName]
150
+ ) as (value: string) => unknown;
151
+ }
152
+ }
153
+
154
+ if (argTypeFunction) {
155
+ argOpts.type = argTypeFunction;
156
+ }
157
+
158
+ if (enumValues && !_.isEmpty(enumValues)) {
159
+ if (type === TYPENAMES.STRING) {
160
+ argOpts.choices = enumValues.map(String);
161
+ } else {
162
+ throw new TypeError(
163
+ `Problem with schema for ${arg}; \`enum\` is only supported for \`type: 'string'\``
164
+ );
165
+ }
166
+ }
167
+
168
+ const finalAliases = aliases as [string] | [string, string];
169
+ return [finalAliases, argOpts];
170
+ }
171
+
@@ -0,0 +1,83 @@
1
+ import {ArgumentTypeError} from 'argparse';
2
+ import {readFileSync, existsSync} from 'node:fs';
3
+
4
+ /**
5
+ * This module provides transformer functions for CLI arguments.
6
+ *
7
+ * Use case: config schemas can accept richer types (arrays/objects), but CLI
8
+ * values are strings. Transformers convert string input into those richer types.
9
+ */
10
+
11
+ /**
12
+ * Splits a CSV string into an array
13
+ */
14
+ export function parseCsvLine(value: string): string[] {
15
+ return value
16
+ .split(',')
17
+ .map((v) => v.trim())
18
+ .filter(Boolean);
19
+ }
20
+
21
+ export const transformers = {
22
+ /**
23
+ * Given a CSV-style string or pathname, parse it into an array.
24
+ * The file can also be split on newlines.
25
+ */
26
+ csv: (csvOrPath: string): string[] => {
27
+ let csv = csvOrPath;
28
+ let loadedFromFile = false;
29
+ // Value could be a single CSV token or a filepath; attempt file first.
30
+ if (existsSync(csvOrPath)) {
31
+ try {
32
+ csv = readFileSync(csvOrPath, 'utf8');
33
+ } catch (err) {
34
+ throw new ArgumentTypeError(`Could not read file '${csvOrPath}': ${(err as Error).message}`);
35
+ }
36
+ loadedFromFile = true;
37
+ }
38
+ try {
39
+ return loadedFromFile ? parseCsvFile(csv) : parseCsvLine(csv);
40
+ } catch (err) {
41
+ const msg = loadedFromFile
42
+ ? `The provided value of '${csvOrPath}' must be a valid CSV`
43
+ : `Must be a comma-delimited string, e.g., "foo,bar,baz"`;
44
+ throw new TypeError(`${msg}. Original error: ${(err as Error).message}`);
45
+ }
46
+ },
47
+
48
+ /**
49
+ * Parse a string which could be a path to a JSON file or a JSON string.
50
+ */
51
+ json: (jsonOrPath: string): Record<string, any> => {
52
+ let json = jsonOrPath;
53
+ let loadedFromFile = false;
54
+ if (existsSync(jsonOrPath)) {
55
+ try {
56
+ // Intentionally sync: argparse type hooks are synchronous.
57
+ json = readFileSync(jsonOrPath, 'utf8');
58
+ } catch (err) {
59
+ throw new ArgumentTypeError(`Could not read file '${jsonOrPath}': ${(err as Error).message}`);
60
+ }
61
+ loadedFromFile = true;
62
+ }
63
+ try {
64
+ return JSON.parse(json);
65
+ } catch (e) {
66
+ const msg = loadedFromFile
67
+ ? `'${jsonOrPath}' must be a valid JSON`
68
+ : `The provided value must be a valid JSON`;
69
+ throw new TypeError(`${msg}. Original error: ${(e as Error).message}`);
70
+ }
71
+ },
72
+ } as const;
73
+
74
+ /**
75
+ * Split a file by newline then calls {@link parseCsvLine} on each line.
76
+ */
77
+ function parseCsvFile(value: string): string[] {
78
+ return value
79
+ .split(/\r?\n/)
80
+ .map((v) => v.trim())
81
+ .filter(Boolean)
82
+ .flatMap(parseCsvLine);
83
+ }
@@ -0,0 +1,43 @@
1
+ import betterAjvErrors, {type IOutputError} from '@sidvind/better-ajv-errors';
2
+ import type {ErrorObject} from 'ajv';
3
+ import type {NormalizedAppiumConfig} from '@appium/types';
4
+ import {getSchema} from './schema';
5
+
6
+ /**
7
+ * The string should be a raw JSON string.
8
+ */
9
+ export type RawJson = string;
10
+
11
+ /**
12
+ * Options for {@link formatErrors}.
13
+ */
14
+ export interface FormatConfigErrorsOptions {
15
+ json?: RawJson;
16
+ pretty?: boolean;
17
+ schemaId?: string;
18
+ }
19
+
20
+ /**
21
+ * Given an array of errors and the result of loading a config file, generate a
22
+ * helpful string for the user.
23
+ *
24
+ * - If `opts` contains a `json` property, this should be the original JSON
25
+ * _string_ of the config file. This is only applicable if the config file
26
+ * was in JSON format. If present, it will associate line numbers with errors.
27
+ * - If `errors` happens to be empty, this will throw.
28
+ *
29
+ * @throws {TypeError} If `errors` is empty
30
+ */
31
+ export function formatErrors(
32
+ errors: ErrorObject[] = [],
33
+ config: NormalizedAppiumConfig | Record<string, unknown> | string | undefined = {},
34
+ opts: FormatConfigErrorsOptions = {}
35
+ ): string | IOutputError[] {
36
+ if (errors && !errors.length) {
37
+ throw new TypeError('Array of errors must be non-empty');
38
+ }
39
+ return betterAjvErrors(getSchema(opts.schemaId), config, errors, {
40
+ json: opts.json,
41
+ format: opts.pretty === false ? 'js' : 'cli',
42
+ });
43
+ }
@@ -0,0 +1,4 @@
1
+ export * from './schema';
2
+ export * from './format-errors';
3
+ export * from './cli-args';
4
+ export * from './cli-args-guards';
@@ -0,0 +1,96 @@
1
+ import type {KeywordDefinition} from 'ajv';
2
+ import {transformers} from './cli-transformers';
3
+
4
+ export type AppiumCliTransformerName = keyof typeof transformers;
5
+
6
+ export interface AppiumJSONSchemaKeywords {
7
+ appiumCliDest?: string;
8
+ appiumCliDescription?: string;
9
+ appiumCliAliases?: string[];
10
+ appiumCliIgnored?: boolean;
11
+ appiumCliTransformer?: AppiumCliTransformerName;
12
+ appiumDeprecated?: boolean;
13
+ }
14
+
15
+ /**
16
+ * Collection of keyword definitions to add to the singleton `Ajv` instance.
17
+ */
18
+ export const keywords: Record<string, KeywordDefinition> = {
19
+ /**
20
+ * List of alias names for a CLI arg.
21
+ */
22
+ appiumCliAliases: {
23
+ keyword: 'appiumCliAliases',
24
+ metaSchema: {
25
+ type: 'array',
26
+ items: {
27
+ type: 'string',
28
+ minLength: 1,
29
+ },
30
+ minItems: 1,
31
+ uniqueItems: true,
32
+ description:
33
+ 'List of aliases for the argument. Aliases shorter than three (3) characters will be prefixed with a single dash; otherwise two (2).',
34
+ },
35
+ },
36
+ /**
37
+ * Explicit destination key name in parsed args.
38
+ */
39
+ appiumCliDest: {
40
+ keyword: 'appiumCliDest',
41
+ metaSchema: {
42
+ type: 'string',
43
+ minLength: 1,
44
+ description: 'Name of the associated property in the parsed CLI arguments object',
45
+ },
46
+ },
47
+ /**
48
+ * CLI-specific description (overrides generic schema description for help text).
49
+ */
50
+ appiumCliDescription: {
51
+ keyword: 'appiumCliDescription',
52
+ schemaType: 'string',
53
+ metaSchema: {
54
+ type: 'string',
55
+ minLength: 1,
56
+ description: 'Description to provide in the --help text of the CLI. Overrides `description`',
57
+ },
58
+ },
59
+ /**
60
+ * Named transformer to apply to CLI value before validation.
61
+ */
62
+ appiumCliTransformer: {
63
+ keyword: 'appiumCliTransformer',
64
+ metaSchema: {
65
+ type: 'string',
66
+ enum: Object.keys(transformers) as AppiumCliTransformerName[],
67
+ description:
68
+ 'The name of a custom transformer to run against the value as provided via the CLI.',
69
+ },
70
+ },
71
+ /**
72
+ * If true, this property is not exposed as a CLI arg.
73
+ */
74
+ appiumCliIgnored: {
75
+ keyword: 'appiumCliIgnored',
76
+ metaSchema: {
77
+ type: 'boolean',
78
+ description:
79
+ 'If `true`, Appium will not provide this property as a CLI argument. This is NOT the same as a "hidden" argument.',
80
+ enum: [true],
81
+ },
82
+ },
83
+ /**
84
+ * Marks property as deprecated for CLI docs/help output.
85
+ */
86
+ appiumDeprecated: {
87
+ keyword: 'appiumDeprecated',
88
+ metaSchema: {
89
+ type: 'boolean',
90
+ description: 'If `true`, this property will be displayed as "deprecated" to the user',
91
+ enum: [true],
92
+ $comment:
93
+ 'JSON schema draft-2019-09 keyword `deprecated` serves the same purpose. This keyword should itself be deprecated if we move to draft-2019-09!',
94
+ },
95
+ },
96
+ };