@appium/docutils 0.1.6 → 0.2.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 +2 -5
- package/build/lib/build/mkdocs.d.ts +58 -0
- package/build/lib/build/mkdocs.d.ts.map +1 -0
- package/build/lib/build/mkdocs.js +80 -0
- package/build/lib/build/mkdocs.js.map +1 -0
- package/build/lib/build/typedoc.d.ts +55 -0
- package/build/lib/build/typedoc.d.ts.map +1 -0
- package/build/lib/build/typedoc.js +120 -0
- package/build/lib/build/typedoc.js.map +1 -0
- package/build/lib/build-api.d.ts +18 -0
- package/build/lib/build-api.d.ts.map +1 -0
- package/build/lib/build-api.js +75 -0
- package/build/lib/build-api.js.map +1 -0
- package/build/lib/build.d.ts +21 -0
- package/build/lib/build.d.ts.map +1 -0
- package/build/lib/build.js +71 -0
- package/build/lib/build.js.map +1 -0
- package/build/lib/builder/deploy.d.ts +89 -0
- package/build/lib/builder/deploy.d.ts.map +1 -0
- package/build/lib/builder/deploy.js +105 -0
- package/build/lib/builder/deploy.js.map +1 -0
- package/build/lib/builder/index.d.ts +5 -0
- package/build/lib/builder/index.d.ts.map +1 -0
- package/build/lib/builder/index.js +21 -0
- package/build/lib/builder/index.js.map +1 -0
- package/build/lib/builder/nav.d.ts +81 -0
- package/build/lib/builder/nav.d.ts.map +1 -0
- package/build/lib/builder/nav.js +280 -0
- package/build/lib/builder/nav.js.map +1 -0
- package/build/lib/builder/reference.d.ts +57 -0
- package/build/lib/builder/reference.d.ts.map +1 -0
- package/build/lib/builder/reference.js +129 -0
- package/build/lib/builder/reference.js.map +1 -0
- package/build/lib/builder/site.d.ts +55 -0
- package/build/lib/builder/site.d.ts.map +1 -0
- package/build/lib/builder/site.js +81 -0
- package/build/lib/builder/site.js.map +1 -0
- package/build/lib/cli/command/build.d.ts +178 -0
- package/build/lib/cli/command/build.d.ts.map +1 -0
- package/build/lib/cli/command/build.js +223 -0
- package/build/lib/cli/command/build.js.map +1 -0
- package/build/lib/cli/command/deploy.d.ts +1 -0
- package/build/lib/cli/command/deploy.d.ts.map +1 -0
- package/build/lib/cli/command/deploy.js +2 -0
- package/build/lib/cli/command/deploy.js.map +1 -0
- package/build/lib/cli/command/index.d.ts +4 -0
- package/build/lib/cli/command/index.d.ts.map +1 -0
- package/build/lib/cli/command/index.js +13 -0
- package/build/lib/cli/command/index.js.map +1 -0
- package/build/lib/cli/command/init.d.ts +143 -0
- package/build/lib/cli/command/init.d.ts.map +1 -0
- package/build/lib/cli/command/init.js +164 -0
- package/build/lib/cli/command/init.js.map +1 -0
- package/build/lib/cli/command/validate.d.ts +76 -0
- package/build/lib/cli/command/validate.d.ts.map +1 -0
- package/build/lib/cli/command/validate.js +115 -0
- package/build/lib/cli/command/validate.js.map +1 -0
- package/build/lib/cli/command-init.d.ts +143 -0
- package/build/lib/cli/command-init.d.ts.map +1 -0
- package/build/lib/cli/command-init.js +164 -0
- package/build/lib/cli/command-init.js.map +1 -0
- package/build/lib/cli/command-validate.d.ts +52 -0
- package/build/lib/cli/command-validate.d.ts.map +1 -0
- package/build/lib/cli/command-validate.js +66 -0
- package/build/lib/cli/command-validate.js.map +1 -0
- package/build/lib/cli/config.d.ts +28 -0
- package/build/lib/cli/config.d.ts.map +1 -0
- package/build/lib/cli/config.js +114 -0
- package/build/lib/cli/config.js.map +1 -0
- package/build/lib/cli/index.d.ts +13 -0
- package/build/lib/cli/index.d.ts.map +1 -0
- package/build/lib/cli/index.js +91 -0
- package/build/lib/cli/index.js.map +1 -0
- package/build/lib/cli/init.d.ts +143 -0
- package/build/lib/cli/init.d.ts.map +1 -0
- package/build/lib/cli/init.js +164 -0
- package/build/lib/cli/init.js.map +1 -0
- package/build/lib/cli/options.d.ts +1 -0
- package/build/lib/cli/options.d.ts.map +1 -0
- package/build/lib/cli/options.js +2 -0
- package/build/lib/cli/options.js.map +1 -0
- package/build/lib/cli/validate.d.ts +1 -0
- package/build/lib/cli/validate.d.ts.map +1 -0
- package/build/lib/cli/validate.js +2 -0
- package/build/lib/cli/validate.js.map +1 -0
- package/build/lib/cli.d.ts +10 -0
- package/build/lib/cli.d.ts.map +1 -0
- package/build/lib/cli.js +328 -0
- package/build/lib/cli.js.map +1 -0
- package/build/lib/constants.d.ts +125 -0
- package/build/lib/constants.d.ts.map +1 -0
- package/build/lib/constants.js +133 -0
- package/build/lib/constants.js.map +1 -0
- package/build/lib/error.d.ts +3 -0
- package/build/lib/error.d.ts.map +1 -0
- package/build/lib/error.js +7 -0
- package/build/lib/error.js.map +1 -0
- package/build/lib/fs.d.ts +142 -0
- package/build/lib/fs.d.ts.map +1 -0
- package/build/lib/fs.js +237 -0
- package/build/lib/fs.js.map +1 -0
- package/build/lib/index.d.ts +5 -2
- package/build/lib/index.d.ts.map +1 -1
- package/build/lib/index.js +4 -1
- package/build/lib/index.js.map +1 -1
- package/build/lib/init-task.d.ts +49 -0
- package/build/lib/init-task.d.ts.map +1 -0
- package/build/lib/init-task.js +95 -0
- package/build/lib/init-task.js.map +1 -0
- package/build/lib/init.d.ts +202 -0
- package/build/lib/init.d.ts.map +1 -0
- package/build/lib/init.js +225 -0
- package/build/lib/init.js.map +1 -0
- package/build/lib/io.d.ts +1 -0
- package/build/lib/io.d.ts.map +1 -0
- package/build/lib/io.js +2 -0
- package/build/lib/io.js.map +1 -0
- package/build/lib/logger.d.ts +17 -2
- package/build/lib/logger.d.ts.map +1 -1
- package/build/lib/logger.js +187 -2
- package/build/lib/logger.js.map +1 -1
- package/build/lib/mike.d.ts +3 -0
- package/build/lib/mike.d.ts.map +1 -1
- package/build/lib/mike.js +4 -0
- package/build/lib/mike.js.map +1 -1
- package/build/lib/mkdocs.d.ts +51 -12
- package/build/lib/mkdocs.d.ts.map +1 -1
- package/build/lib/mkdocs.js +64 -32
- package/build/lib/mkdocs.js.map +1 -1
- package/build/lib/model.d.ts +80 -0
- package/build/lib/model.d.ts.map +1 -0
- package/build/lib/model.js +8 -0
- package/build/lib/model.js.map +1 -0
- package/build/lib/nav.d.ts +47 -0
- package/build/lib/nav.d.ts.map +1 -0
- package/build/lib/nav.js +132 -0
- package/build/lib/nav.js.map +1 -0
- package/build/lib/scaffold.d.ts +95 -0
- package/build/lib/scaffold.d.ts.map +1 -0
- package/build/lib/scaffold.js +103 -0
- package/build/lib/scaffold.js.map +1 -0
- package/build/lib/test.d.ts +9 -0
- package/build/lib/test.d.ts.map +1 -0
- package/build/lib/test.js +2 -0
- package/build/lib/test.js.map +1 -0
- package/build/lib/typedoc.d.ts +55 -0
- package/build/lib/typedoc.d.ts.map +1 -0
- package/build/lib/typedoc.js +122 -0
- package/build/lib/typedoc.js.map +1 -0
- package/build/lib/types.d.ts +52 -0
- package/build/lib/types.d.ts.map +1 -0
- package/build/lib/types.js +7 -0
- package/build/lib/types.js.map +1 -0
- package/build/lib/util.d.ts +42 -0
- package/build/lib/util.d.ts.map +1 -0
- package/build/lib/util.js +56 -0
- package/build/lib/util.js.map +1 -0
- package/build/lib/validate.d.ts +218 -0
- package/build/lib/validate.d.ts.map +1 -0
- package/build/lib/validate.js +501 -0
- package/build/lib/validate.js.map +1 -0
- package/build/lib/validation/base-validator.d.ts +218 -0
- package/build/lib/validation/base-validator.d.ts.map +1 -0
- package/build/lib/validation/base-validator.js +453 -0
- package/build/lib/validation/base-validator.js.map +1 -0
- package/build/lib/validation/mkdocs-validator.d.ts +5 -0
- package/build/lib/validation/mkdocs-validator.d.ts.map +1 -0
- package/build/lib/validation/mkdocs-validator.js +54 -0
- package/build/lib/validation/mkdocs-validator.js.map +1 -0
- package/build/lib/validation/python-validator.d.ts +1 -0
- package/build/lib/validation/python-validator.d.ts.map +1 -0
- package/build/lib/validation/python-validator.js +2 -0
- package/build/lib/validation/python-validator.js.map +1 -0
- package/build/lib/validation/python.d.ts +1 -0
- package/build/lib/validation/python.d.ts.map +1 -0
- package/build/lib/validation/python.js +2 -0
- package/build/lib/validation/python.js.map +1 -0
- package/build/lib/validation/validate.d.ts +221 -0
- package/build/lib/validation/validate.d.ts.map +1 -0
- package/build/lib/validation/validate.js +508 -0
- package/build/lib/validation/validate.js.map +1 -0
- package/build/lib/validation/validator.d.ts +220 -0
- package/build/lib/validation/validator.d.ts.map +1 -0
- package/build/lib/validation/validator.js +470 -0
- package/build/lib/validation/validator.js.map +1 -0
- package/lib/builder/deploy.ts +223 -0
- package/lib/builder/index.ts +4 -0
- package/lib/builder/nav.ts +399 -0
- package/lib/builder/reference.ts +191 -0
- package/lib/builder/site.ts +143 -0
- package/lib/cli/command/build.ts +229 -0
- package/lib/cli/command/index.ts +3 -0
- package/lib/cli/command/init.ts +166 -0
- package/lib/cli/command/validate.ts +122 -0
- package/lib/cli/config.ts +89 -0
- package/lib/cli/index.ts +88 -0
- package/lib/constants.ts +150 -0
- package/lib/error.ts +1 -0
- package/lib/fs.ts +274 -0
- package/lib/index.ts +5 -0
- package/lib/init.ts +319 -0
- package/lib/logger.ts +198 -0
- package/lib/mike.js +4 -0
- package/lib/model.ts +92 -0
- package/lib/scaffold.ts +225 -0
- package/lib/util.ts +76 -0
- package/lib/validate.ts +728 -0
- package/package.json +38 -6
- package/requirements.txt +4 -0
- package/tsconfig.json +2 -1
- package/build/tsconfig.tsbuildinfo +0 -1
- package/lib/index.js +0 -2
- package/lib/logger.js +0 -3
- package/lib/mkdocs.js +0 -43
package/lib/logger.ts
ADDED
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* It's a logger.
|
|
3
|
+
*
|
|
4
|
+
* Since this is a CLI app only, it doesn't necessarily make sense to consume `@appium/support`'s logger.
|
|
5
|
+
*
|
|
6
|
+
* @module
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import figures from 'figures';
|
|
10
|
+
import logSymbols from 'log-symbols';
|
|
11
|
+
import chalk, {ForegroundColor, BackgroundColor} from 'chalk';
|
|
12
|
+
import consola, {
|
|
13
|
+
logType as LogType,
|
|
14
|
+
ConsolaReporterLogObject,
|
|
15
|
+
FancyReporter,
|
|
16
|
+
FancyReporterOptions,
|
|
17
|
+
Consola,
|
|
18
|
+
ConsolaOptions,
|
|
19
|
+
LogLevel,
|
|
20
|
+
} from 'consola';
|
|
21
|
+
import {DEFAULT_LOG_LEVEL, LogLevelMap} from './constants';
|
|
22
|
+
import _ from 'lodash';
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* This is a reporter for `consola` which uses some extra/custom icons and colors.
|
|
26
|
+
*
|
|
27
|
+
* @privateRemarks
|
|
28
|
+
* I did not like that the default `FancyReport` logs errors in _green_ without any sort of icon.
|
|
29
|
+
* Both `log-symbols` and `consola` consume `chalk`, so we do too. `consola` also depends on `figures`.
|
|
30
|
+
*/
|
|
31
|
+
class DocutilsReporter extends FancyReporter {
|
|
32
|
+
/**
|
|
33
|
+
* Mapping of log types (the name of the logging method called) to chalk fg colors
|
|
34
|
+
*/
|
|
35
|
+
static TYPE_COLOR_MAP = {
|
|
36
|
+
info: 'cyan',
|
|
37
|
+
success: 'green',
|
|
38
|
+
error: 'red',
|
|
39
|
+
warn: 'yellow',
|
|
40
|
+
} as const;
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Mapping of log levels to chalk fg colors
|
|
44
|
+
*/
|
|
45
|
+
static LEVEL_COLORS = {
|
|
46
|
+
0: 'red',
|
|
47
|
+
1: 'yellow',
|
|
48
|
+
2: 'white',
|
|
49
|
+
3: 'green',
|
|
50
|
+
} as const;
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Mapping of log types to icons/symbols
|
|
54
|
+
*/
|
|
55
|
+
static TYPE_ICONS = {
|
|
56
|
+
info: logSymbols.info,
|
|
57
|
+
success: logSymbols.success,
|
|
58
|
+
error: logSymbols.error,
|
|
59
|
+
warn: logSymbols.warning,
|
|
60
|
+
debug: figures('›'),
|
|
61
|
+
trace: figures('›'),
|
|
62
|
+
} as const;
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Default color to use if we can't find a color for the log type or level
|
|
66
|
+
*/
|
|
67
|
+
static readonly DEFAULT_COLOR = 'grey';
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Type guard to check if a log type has a color
|
|
71
|
+
* @param type A log type
|
|
72
|
+
*/
|
|
73
|
+
static hasTypeColor(type: LogType): type is keyof typeof DocutilsReporter.TYPE_COLOR_MAP {
|
|
74
|
+
return type in DocutilsReporter.TYPE_COLOR_MAP;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Type guard to check if a log level has a color
|
|
79
|
+
* @param level A log level
|
|
80
|
+
*/
|
|
81
|
+
static hasLevelColor(level: LogLevel): level is keyof typeof DocutilsReporter.LEVEL_COLORS {
|
|
82
|
+
return level in DocutilsReporter.LEVEL_COLORS;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Type guard to check if a log type has an icon
|
|
87
|
+
* @param type A log type
|
|
88
|
+
*/
|
|
89
|
+
static hasTypeIcon(type: LogType): type is keyof typeof DocutilsReporter.TYPE_ICONS {
|
|
90
|
+
return type in DocutilsReporter.TYPE_ICONS;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Prefixes the logging output with colors and symbols, depending on contents of `logObj`.
|
|
95
|
+
* @param logObj Consola's log object
|
|
96
|
+
* @param isBadge {@linkcode FancyReporter} uses this; I think it depends on the terminal width
|
|
97
|
+
* @returns
|
|
98
|
+
*/
|
|
99
|
+
protected override formatType(logObj: ConsolaReporterLogObject, isBadge?: boolean): string {
|
|
100
|
+
const {
|
|
101
|
+
TYPE_COLOR_MAP,
|
|
102
|
+
LEVEL_COLORS,
|
|
103
|
+
TYPE_ICONS,
|
|
104
|
+
hasTypeColor,
|
|
105
|
+
hasLevelColor,
|
|
106
|
+
hasTypeIcon,
|
|
107
|
+
DEFAULT_COLOR,
|
|
108
|
+
} = DocutilsReporter;
|
|
109
|
+
|
|
110
|
+
let typeColor: typeof ForegroundColor;
|
|
111
|
+
if (hasTypeColor(logObj.type)) {
|
|
112
|
+
typeColor = TYPE_COLOR_MAP[logObj.type];
|
|
113
|
+
} else if (hasLevelColor(logObj.level)) {
|
|
114
|
+
typeColor = LEVEL_COLORS[logObj.level];
|
|
115
|
+
} else {
|
|
116
|
+
typeColor = <typeof ForegroundColor>(
|
|
117
|
+
((this.options as FancyReporterOptions).secondaryColor ?? DEFAULT_COLOR)
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
if (isBadge) {
|
|
122
|
+
return chalk[('bg' + _.capitalize(typeColor)) as typeof BackgroundColor].black(
|
|
123
|
+
` ${_.toUpper(logObj.type)}`
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
const type = hasTypeIcon(logObj.type) ? TYPE_ICONS[logObj.type] : logObj.type;
|
|
128
|
+
return type ? chalk[typeColor](type) : '';
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* The global log level
|
|
134
|
+
*
|
|
135
|
+
* "Global" inasmuch as any logger created from the root logger will use this level.
|
|
136
|
+
*/
|
|
137
|
+
let globalLevel = LogLevelMap[DEFAULT_LOG_LEVEL];
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* The logger from which all loggers are created. This one uses a unique tag and our custom reporter.
|
|
141
|
+
*/
|
|
142
|
+
const rootLogger = createLogProxy(
|
|
143
|
+
consola.create({defaults: {tag: 'docutils'}, reporters: [new DocutilsReporter()]})
|
|
144
|
+
);
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* @summary Creates a log-level-propagating proxy for a {@linkcode Consola} logger.
|
|
148
|
+
* @description
|
|
149
|
+
* Alright. So when you create a new logger via {@linkcode Consola.create}, it's basically a clone
|
|
150
|
+
* of its parent with a new set of options.
|
|
151
|
+
*
|
|
152
|
+
* If we change the log level of the root logger (which we do: see `cli/index.ts`), we may (almost
|
|
153
|
+
* certainly) have
|
|
154
|
+
* child loggers which: a) have already been created and b) have inherited the old/default log level
|
|
155
|
+
* from the root logger. We don't _want_ that (though this is likely a reasonable use case) for our
|
|
156
|
+
* purposes.
|
|
157
|
+
*
|
|
158
|
+
* The implementation below solves the problem by maintaining its own singleton log level value, and
|
|
159
|
+
* intercepts the `level` property of any logger created from the root logger.
|
|
160
|
+
*
|
|
161
|
+
* There are other ways to go about this which may be better, but this seemed pretty straightforward.
|
|
162
|
+
*/
|
|
163
|
+
function createLogProxy(logger: Consola): Consola {
|
|
164
|
+
return new Proxy(logger, {
|
|
165
|
+
get(target, prop, receiver) {
|
|
166
|
+
if (prop === 'level') {
|
|
167
|
+
return globalLevel;
|
|
168
|
+
}
|
|
169
|
+
if (prop === 'create') {
|
|
170
|
+
const create = Reflect.get(target, prop, receiver) as Consola['create'];
|
|
171
|
+
return (opts: ConsolaOptions) => createLogProxy(create.call(receiver, opts));
|
|
172
|
+
}
|
|
173
|
+
if (prop === '_defaults') {
|
|
174
|
+
const defaults = Reflect.get(target, prop, receiver);
|
|
175
|
+
return {...defaults, level: globalLevel};
|
|
176
|
+
}
|
|
177
|
+
return Reflect.get(target, prop, receiver);
|
|
178
|
+
},
|
|
179
|
+
set(target, prop, value, receiver) {
|
|
180
|
+
if (prop === 'level') {
|
|
181
|
+
globalLevel = value as LogLevel;
|
|
182
|
+
return true;
|
|
183
|
+
}
|
|
184
|
+
return Reflect.set(target, prop, value, receiver);
|
|
185
|
+
},
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* The proxied root logger
|
|
191
|
+
* @see {createLogProxy}
|
|
192
|
+
*/
|
|
193
|
+
export default rootLogger;
|
|
194
|
+
|
|
195
|
+
// these are just type-sanity checks
|
|
196
|
+
<{[k in LogType]?: typeof ForegroundColor}>DocutilsReporter.TYPE_COLOR_MAP;
|
|
197
|
+
<{[k in LogLevel]?: typeof ForegroundColor}>DocutilsReporter.LEVEL_COLORS;
|
|
198
|
+
<{[k in LogType]?: string}>DocutilsReporter.TYPE_ICONS;
|
package/lib/mike.js
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
import {exec} from 'teen_process';
|
|
2
|
+
// eslint-disable-next-line import/no-unresolved
|
|
2
3
|
import log from './logger';
|
|
3
4
|
|
|
4
5
|
const DEFAULT_REMOTE = 'origin';
|
|
5
6
|
const DEFAULT_BRANCH = 'gh-pages';
|
|
6
7
|
const MIKE_VER_STRING = 'mike 1.';
|
|
7
8
|
|
|
9
|
+
/**
|
|
10
|
+
* @deprecated Use the `deploy` export from `@appium/docutils`
|
|
11
|
+
*/
|
|
8
12
|
export class Mike {
|
|
9
13
|
/** @type {string} */ remote;
|
|
10
14
|
/** @type {string} */ branch;
|
package/lib/model.ts
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Various data models, mostly referring to config files
|
|
3
|
+
*
|
|
4
|
+
* @module
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type {Jsonify, JsonValue, TsConfigJson as TsConfigJsonBase} from 'type-fest';
|
|
8
|
+
import type {TypeDocOptions} from 'typedoc';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* A `tsconfig.json` file w/ `$schema` prop
|
|
12
|
+
*
|
|
13
|
+
* Due to some `unknown` types in {@linkcode type-fest.TsConfigJson}, we cannot use that type
|
|
14
|
+
* directly and need to use `Jsonify`.
|
|
15
|
+
*
|
|
16
|
+
*/
|
|
17
|
+
export type TsConfigJson = Jsonify<
|
|
18
|
+
TsConfigJsonBase & {
|
|
19
|
+
$schema?: string;
|
|
20
|
+
}
|
|
21
|
+
>;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* A `typedoc.json` file w/ `$schema` and `extends` props
|
|
25
|
+
*
|
|
26
|
+
* TypeDoc doesn't recognize `$schema` and ignores it; its own config parser expands the value of
|
|
27
|
+
* `extends` before it reaches its `Options` class. This is why we cannot use `TypeDocOptions` directly.
|
|
28
|
+
*/
|
|
29
|
+
export type TypeDocJson = Jsonify<
|
|
30
|
+
Partial<TypeDocOptions> & {
|
|
31
|
+
$schema?: string;
|
|
32
|
+
extends?: string;
|
|
33
|
+
}
|
|
34
|
+
>;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* The `nav` prop of an `mkdocs.yml` file
|
|
38
|
+
* @see {@linkcode MkDocsYml}
|
|
39
|
+
*/
|
|
40
|
+
export type MkDocsYmlNav = Array<string | Record<string, string> | Record<string, MkDocsYmlNav>>;
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* This was built by hand from the MkDocs documentation
|
|
44
|
+
* @see https://www.mkdocs.org/user-guide/configuration/
|
|
45
|
+
*/
|
|
46
|
+
export type MkDocsYml = Jsonify<{
|
|
47
|
+
copyright?: string;
|
|
48
|
+
dev_addr?: string;
|
|
49
|
+
docs_dir?: string;
|
|
50
|
+
extra_css?: string[];
|
|
51
|
+
extra_javascript?: string[];
|
|
52
|
+
extra_templates?: string[];
|
|
53
|
+
extra?: Record<string, JsonValue>;
|
|
54
|
+
hooks?: string[];
|
|
55
|
+
INHERIT?: string;
|
|
56
|
+
markdown_extensions?: Array<string | Record<string, JsonValue>>;
|
|
57
|
+
nav?: MkDocsYmlNav;
|
|
58
|
+
plugins?: Array<string | Record<string, JsonValue>>;
|
|
59
|
+
repo_name?: string;
|
|
60
|
+
repo_url?: string;
|
|
61
|
+
site_dir?: string;
|
|
62
|
+
/**
|
|
63
|
+
* This is _actually_ required by mkdocs
|
|
64
|
+
*/
|
|
65
|
+
site_name?: string;
|
|
66
|
+
site_description?: string;
|
|
67
|
+
strict?: boolean;
|
|
68
|
+
theme?: MkDocsYmlTheme;
|
|
69
|
+
use_directory_urls?: boolean;
|
|
70
|
+
watch?: string[];
|
|
71
|
+
}>;
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* The `theme` prop of an `mkdocs.yml`
|
|
75
|
+
* @see {@linkcode MkDocsYml}
|
|
76
|
+
*/
|
|
77
|
+
export type MkDocsYmlTheme =
|
|
78
|
+
| string
|
|
79
|
+
| ({
|
|
80
|
+
name: string;
|
|
81
|
+
locale?: string;
|
|
82
|
+
custom_dir?: string;
|
|
83
|
+
static_templates?: string[];
|
|
84
|
+
} & Record<string, JsonValue>);
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* The data parsed from a `requirements.txt` file, or the output of `pip list --json`
|
|
88
|
+
*/
|
|
89
|
+
export interface PipPackage {
|
|
90
|
+
name: string;
|
|
91
|
+
version: string;
|
|
92
|
+
}
|
package/lib/scaffold.ts
ADDED
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Implementation of a generic "create and/or update some file" task
|
|
3
|
+
* @module
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import {fs} from '@appium/support';
|
|
7
|
+
import logger from './logger';
|
|
8
|
+
import path from 'node:path';
|
|
9
|
+
import {createPatch} from 'diff';
|
|
10
|
+
import {NormalizedPackageJson} from 'read-pkg';
|
|
11
|
+
import {JsonValue, JsonObject} from 'type-fest';
|
|
12
|
+
import {DocutilsError} from './error';
|
|
13
|
+
import {relative} from './util';
|
|
14
|
+
import _ from 'lodash';
|
|
15
|
+
import {stringifyJson, readPackageJson, safeWriteFile} from './fs';
|
|
16
|
+
import {NAME_ERR_ENOENT, NAME_ERR_EEXIST} from './constants';
|
|
17
|
+
|
|
18
|
+
const log = logger.withTag('init');
|
|
19
|
+
const dryRunLog = log.withTag('dry-run');
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Creates a unified patch for display in "dry run" mode
|
|
23
|
+
* @param filename - File name to use
|
|
24
|
+
* @param oldData - Old data
|
|
25
|
+
* @param newData - New Data
|
|
26
|
+
* @returns Patch string
|
|
27
|
+
*/
|
|
28
|
+
function makePatch<T extends JsonValue>(
|
|
29
|
+
filename: string,
|
|
30
|
+
oldData: T | string,
|
|
31
|
+
newData: T | string,
|
|
32
|
+
serializer: ScaffoldTaskSerializer<T> = stringifyJson
|
|
33
|
+
) {
|
|
34
|
+
return createPatch(
|
|
35
|
+
filename,
|
|
36
|
+
_.isString(oldData) ? oldData : serializer(oldData),
|
|
37
|
+
_.isString(newData) ? newData : serializer(newData)
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Options for a task which are not the {@link ScaffoldTaskOptions base options}
|
|
43
|
+
*/
|
|
44
|
+
export type TaskSpecificOpts<Opts extends ScaffoldTaskOptions> = Omit<
|
|
45
|
+
Opts,
|
|
46
|
+
keyof ScaffoldTaskOptions
|
|
47
|
+
>;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* A function which performs some scaffolding task.
|
|
51
|
+
*
|
|
52
|
+
* @see {@linkcode createScaffoldTask}
|
|
53
|
+
*/
|
|
54
|
+
export type ScaffoldTask<Opts extends ScaffoldTaskOptions, T extends JsonObject> = (
|
|
55
|
+
opts: Opts
|
|
56
|
+
) => Promise<ScaffoldTaskResult<T>>;
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Factory for a {@linkcode ScaffoldTask}.
|
|
60
|
+
*
|
|
61
|
+
* @param defaultFilename Default file to create
|
|
62
|
+
* @param defaultContent Default content to use
|
|
63
|
+
* @param description Description of task
|
|
64
|
+
* @param opts Options
|
|
65
|
+
* @returns A scaffold task
|
|
66
|
+
*/
|
|
67
|
+
export function createScaffoldTask<Opts extends ScaffoldTaskOptions, T extends JsonObject>(
|
|
68
|
+
defaultFilename: string,
|
|
69
|
+
defaultContent: T,
|
|
70
|
+
description: string,
|
|
71
|
+
{
|
|
72
|
+
transform = _.identity,
|
|
73
|
+
deserialize = JSON.parse,
|
|
74
|
+
serialize = stringifyJson,
|
|
75
|
+
}: CreateScaffoldTaskOptions<Opts, T> = {}
|
|
76
|
+
): ScaffoldTask<Opts, T> {
|
|
77
|
+
return async ({
|
|
78
|
+
overwrite = false,
|
|
79
|
+
cwd = process.cwd(),
|
|
80
|
+
packageJson: packageJsonPath,
|
|
81
|
+
dest,
|
|
82
|
+
dryRun = false,
|
|
83
|
+
...opts
|
|
84
|
+
}: Opts): Promise<ScaffoldTaskResult<T>> => {
|
|
85
|
+
const relativePath = relative(cwd);
|
|
86
|
+
const {pkgPath, pkg} = await readPackageJson(
|
|
87
|
+
packageJsonPath ? path.dirname(packageJsonPath) : cwd,
|
|
88
|
+
true
|
|
89
|
+
);
|
|
90
|
+
const pkgDir = path.dirname(pkgPath);
|
|
91
|
+
dest = dest ?? path.join(pkgDir, defaultFilename);
|
|
92
|
+
const relativeDest = relativePath(dest);
|
|
93
|
+
log.debug('Initializing %s', relativeDest);
|
|
94
|
+
let shouldWriteDest = false;
|
|
95
|
+
let destContent: T;
|
|
96
|
+
let result: ScaffoldTaskResult<T>;
|
|
97
|
+
try {
|
|
98
|
+
destContent = deserialize(await fs.readFile(dest, 'utf8'));
|
|
99
|
+
log.debug('Found existing file %s', relativeDest);
|
|
100
|
+
} catch (e) {
|
|
101
|
+
const err = e as NodeJS.ErrnoException;
|
|
102
|
+
if (err.code !== NAME_ERR_ENOENT) {
|
|
103
|
+
throw err;
|
|
104
|
+
}
|
|
105
|
+
shouldWriteDest = true;
|
|
106
|
+
log.debug('Creating new file %s', relativeDest);
|
|
107
|
+
destContent = {} as T;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const defaults: T = transform(defaultContent, opts, pkg);
|
|
111
|
+
const finalDestContent: T = _.defaultsDeep({}, destContent, defaults);
|
|
112
|
+
|
|
113
|
+
shouldWriteDest = shouldWriteDest || !_.isEqual(destContent, finalDestContent);
|
|
114
|
+
|
|
115
|
+
if (shouldWriteDest) {
|
|
116
|
+
log.info('Changes needed to %s', relativeDest);
|
|
117
|
+
log.debug('Original %s: %O', relativeDest, destContent);
|
|
118
|
+
log.debug('Final %s: %O', relativeDest, finalDestContent);
|
|
119
|
+
const patch = makePatch(dest, destContent, finalDestContent, serialize);
|
|
120
|
+
|
|
121
|
+
if (dryRun) {
|
|
122
|
+
dryRunLog.info('Would apply the following patch: \n\n%s', patch);
|
|
123
|
+
result = {path: dest, content: finalDestContent};
|
|
124
|
+
return result;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
try {
|
|
128
|
+
await safeWriteFile(dest, finalDestContent, overwrite);
|
|
129
|
+
} catch (e) {
|
|
130
|
+
const err = e as NodeJS.ErrnoException;
|
|
131
|
+
// this should only be thrown if `force` is false
|
|
132
|
+
if (err.code === NAME_ERR_EEXIST) {
|
|
133
|
+
log.info(`${relativeDest} already exists; continuing...`);
|
|
134
|
+
log.debug(`Tried to apply patch:\n\n${patch}`);
|
|
135
|
+
} else {
|
|
136
|
+
throw new DocutilsError(`Could not write to ${relativeDest}. Reason: ${err.message}`, {
|
|
137
|
+
cause: err,
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
} else {
|
|
142
|
+
log.info('No changes to %s', relativeDest);
|
|
143
|
+
}
|
|
144
|
+
log.success('Initialized %s', description);
|
|
145
|
+
return {path: dest, content: finalDestContent};
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Optional function which can be used to post-process the content of a file. Usually used to merge
|
|
151
|
+
* various options with existing content
|
|
152
|
+
*/
|
|
153
|
+
export type ScaffoldTaskTransformer<Opts extends ScaffoldTaskOptions, T extends JsonValue> = (
|
|
154
|
+
content: Readonly<T>,
|
|
155
|
+
opts: TaskSpecificOpts<Opts>,
|
|
156
|
+
pkg: NormalizedPackageJson
|
|
157
|
+
) => T;
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* A function which deserializes a string into a JS value.
|
|
161
|
+
*/
|
|
162
|
+
export type ScaffoldTaskDeserializer<T> = (content: string) => T;
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* A function which serializes a JS value into a string.
|
|
166
|
+
*/
|
|
167
|
+
export type ScaffoldTaskSerializer<T> = (content: T) => string;
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Options for {@linkcode createScaffoldTask}
|
|
171
|
+
*/
|
|
172
|
+
export interface CreateScaffoldTaskOptions<Opts extends ScaffoldTaskOptions, T extends JsonValue> {
|
|
173
|
+
/**
|
|
174
|
+
* Transformer function
|
|
175
|
+
*/
|
|
176
|
+
transform?: ScaffoldTaskTransformer<Opts, T>;
|
|
177
|
+
/**
|
|
178
|
+
* Deserializer function
|
|
179
|
+
*/
|
|
180
|
+
deserialize?: ScaffoldTaskDeserializer<T>;
|
|
181
|
+
/**
|
|
182
|
+
* Serializer function
|
|
183
|
+
*/
|
|
184
|
+
serialize?: ScaffoldTaskSerializer<T>;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Base options for all scaffold tasks
|
|
189
|
+
*/
|
|
190
|
+
export interface ScaffoldTaskOptions {
|
|
191
|
+
/**
|
|
192
|
+
* Current working directory
|
|
193
|
+
*/
|
|
194
|
+
cwd?: string;
|
|
195
|
+
/**
|
|
196
|
+
* Destination file
|
|
197
|
+
*/
|
|
198
|
+
dest?: string;
|
|
199
|
+
/**
|
|
200
|
+
* If `true` will not write files
|
|
201
|
+
*/
|
|
202
|
+
dryRun?: boolean;
|
|
203
|
+
/**
|
|
204
|
+
* If `true` will overwrite fields in `typedoc.json`
|
|
205
|
+
*/
|
|
206
|
+
overwrite?: boolean;
|
|
207
|
+
/**
|
|
208
|
+
* Path to `package.json`
|
|
209
|
+
*/
|
|
210
|
+
packageJson?: string;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* The return value of a {@linkcode ScaffoldTask}
|
|
215
|
+
*/
|
|
216
|
+
export interface ScaffoldTaskResult<T> {
|
|
217
|
+
/**
|
|
218
|
+
* The content of whatever it wrote or would write
|
|
219
|
+
*/
|
|
220
|
+
content: T;
|
|
221
|
+
/**
|
|
222
|
+
* The filepath of whatever it wrote or would write
|
|
223
|
+
*/
|
|
224
|
+
path: string;
|
|
225
|
+
}
|
package/lib/util.ts
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utilities
|
|
3
|
+
* @module
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import _ from 'lodash';
|
|
7
|
+
import path from 'node:path';
|
|
8
|
+
import type {SubProcess} from 'teen_process';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Computes a relative path, prepending `./`
|
|
12
|
+
*/
|
|
13
|
+
export const relative = _.curry(
|
|
14
|
+
(from: string, to: string): string => `.${path.sep}${path.relative(from, to)}`
|
|
15
|
+
);
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* A stopwatch-like thing
|
|
19
|
+
*
|
|
20
|
+
* Used for displaying elapsed time in milliseconds
|
|
21
|
+
* @param id - Unique identifier
|
|
22
|
+
* @returns Function that returns the elapsed time in milliseconds
|
|
23
|
+
*/
|
|
24
|
+
export function stopwatch(id: string) {
|
|
25
|
+
const start = Date.now();
|
|
26
|
+
stopwatch.cache.set(id, start);
|
|
27
|
+
return () => {
|
|
28
|
+
const result = Date.now() - stopwatch.cache.get(id)!;
|
|
29
|
+
stopwatch.cache.delete(id);
|
|
30
|
+
return result;
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
stopwatch.cache = new Map<string, number>();
|
|
34
|
+
|
|
35
|
+
export type TupleToObject<
|
|
36
|
+
T extends readonly any[],
|
|
37
|
+
M extends Record<Exclude<keyof T, keyof any[]>, PropertyKey>
|
|
38
|
+
> = {[K in Exclude<keyof T, keyof any[]> as M[K]]: T[K]};
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Type guard to narrow an array to a string array
|
|
42
|
+
* @param value any value
|
|
43
|
+
* @returns `true` if the array is `string[]`
|
|
44
|
+
*/
|
|
45
|
+
export const isStringArray = _.overEvery(_.isArray, _.partial(_.every, _, _.isString)) as (
|
|
46
|
+
value: any
|
|
47
|
+
) => value is string[];
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Converts an object of string values to an array of arguments for CLI
|
|
51
|
+
*
|
|
52
|
+
* Supports `boolean` and `number` values as well. `boolean`s are assumed to be flags which default
|
|
53
|
+
* to `false`, so they will only be added to the array if the value is `true`.
|
|
54
|
+
*/
|
|
55
|
+
export const argify: (obj: Record<string, string | number | boolean | undefined>) => string[] =
|
|
56
|
+
_.flow(
|
|
57
|
+
_.entries,
|
|
58
|
+
_.flatten,
|
|
59
|
+
(list) =>
|
|
60
|
+
list.map((value, idx) => {
|
|
61
|
+
if (value === true) {
|
|
62
|
+
return `--${value}`;
|
|
63
|
+
} else if (value === false || value === undefined) {
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
return idx % 2 === 0 ? `--${value}` : value;
|
|
67
|
+
}),
|
|
68
|
+
_.compact
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Conversion of the parameters of {@linkcode Subprocess.start} to an object.
|
|
73
|
+
*/
|
|
74
|
+
export type TeenProcessSubprocessStartOpts = Partial<
|
|
75
|
+
TupleToObject<Parameters<SubProcess['start']>, ['startDetector', 'detach', 'timeoutMs']>
|
|
76
|
+
>;
|