depflow 3.0.0-dev.10 → 3.0.0-dev.11

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 (172) hide show
  1. package/README.md +108 -43
  2. package/dist/builder/Builder.d.ts +279 -0
  3. package/dist/builder/Builder.js +391 -0
  4. package/dist/builder/Builder.js.map +1 -0
  5. package/dist/cli/CLI.d.ts +157 -0
  6. package/dist/cli/CLI.js +214 -0
  7. package/dist/cli/CLI.js.map +1 -0
  8. package/dist/cli/DepFLowCLI.d.ts +93 -0
  9. package/dist/cli/DepFLowCLI.js +413 -0
  10. package/dist/cli/DepFLowCLI.js.map +1 -0
  11. package/dist/cli/Flags.d.ts +106 -0
  12. package/dist/cli/Flags.js +125 -0
  13. package/dist/cli/Flags.js.map +1 -0
  14. package/dist/cli/bin.js +68 -0
  15. package/dist/cli/bin.js.map +1 -0
  16. package/dist/config/Config.d.ts +690 -0
  17. package/dist/config/Config.js +45 -0
  18. package/dist/config/Config.js.map +1 -0
  19. package/dist/config/ImportMap.d.ts +60 -0
  20. package/dist/config/ImportMap.js +66 -0
  21. package/dist/config/ImportMap.js.map +1 -0
  22. package/dist/config/JsonSchema.d.ts +12 -0
  23. package/dist/config/JsonSchema.js +26 -0
  24. package/dist/config/JsonSchema.js.map +1 -0
  25. package/dist/config/Settings.d.ts +201 -0
  26. package/dist/config/Settings.js +191 -0
  27. package/dist/config/Settings.js.map +1 -0
  28. package/dist/config/TSConfig.d.ts +73 -0
  29. package/dist/config/TSConfig.js +73 -0
  30. package/dist/config/TSConfig.js.map +1 -0
  31. package/dist/config/codecs/JsonCodec.d.ts +30 -0
  32. package/dist/config/codecs/JsonCodec.js +31 -0
  33. package/dist/config/codecs/JsonCodec.js.map +1 -0
  34. package/dist/config/codecs/YamlCodec.d.ts +62 -0
  35. package/dist/config/codecs/YamlCodec.js +89 -0
  36. package/dist/config/codecs/YamlCodec.js.map +1 -0
  37. package/dist/dependency/DepUtils.d.ts +50 -0
  38. package/dist/dependency/DepUtils.js +71 -0
  39. package/dist/dependency/DepUtils.js.map +1 -0
  40. package/dist/dependency/Dependency.d.ts +81 -0
  41. package/dist/dependency/Dependency.js +71 -0
  42. package/dist/dependency/Dependency.js.map +1 -0
  43. package/dist/dependency/Git.d.ts +75 -0
  44. package/dist/dependency/Git.js +97 -0
  45. package/dist/dependency/Git.js.map +1 -0
  46. package/dist/dependency/GitDependency.d.ts +30 -0
  47. package/dist/dependency/GitDependency.js +79 -0
  48. package/dist/dependency/GitDependency.js.map +1 -0
  49. package/dist/dependency/NpmDependency.d.ts +27 -0
  50. package/dist/dependency/NpmDependency.js +91 -0
  51. package/dist/dependency/NpmDependency.js.map +1 -0
  52. package/{build/support/PathResolver → dist/resolve}/AliasCompiler.d.ts +18 -5
  53. package/{build/support/PathResolver → dist/resolve}/AliasCompiler.js +31 -9
  54. package/dist/resolve/AliasCompiler.js.map +1 -0
  55. package/{build/support/PathResolver → dist/resolve}/PathResolver.d.ts +25 -8
  56. package/dist/resolve/PathResolver.js +133 -0
  57. package/dist/resolve/PathResolver.js.map +1 -0
  58. package/dist/resolve/PathRewriter.d.ts +24 -0
  59. package/{build/support/PathResolver → dist/resolve}/PathRewriter.js +21 -11
  60. package/dist/resolve/PathRewriter.js.map +1 -0
  61. package/{build → dist}/schema/Config/Builder.d.ts +114 -49
  62. package/dist/schema/Config/Builder.js +78 -0
  63. package/dist/schema/Config/Builder.js.map +1 -0
  64. package/{build → dist}/schema/Config/Config.d.ts +169 -78
  65. package/dist/schema/Config/Config.js +62 -0
  66. package/dist/schema/Config/Config.js.map +1 -0
  67. package/{build → dist}/schema/Config/Dependency.d.ts +219 -89
  68. package/dist/schema/Config/Dependency.js +80 -0
  69. package/dist/schema/Config/Dependency.js.map +1 -0
  70. package/{build → dist}/schema/Config/Extractor.d.ts +41 -17
  71. package/dist/schema/Config/Extractor.js +43 -0
  72. package/dist/schema/Config/Extractor.js.map +1 -0
  73. package/{build → dist}/schema/Config/Resolver.d.ts +25 -8
  74. package/dist/schema/Config/Resolver.js +43 -0
  75. package/dist/schema/Config/Resolver.js.map +1 -0
  76. package/{build → dist}/schema/Config/Transform.d.ts +22 -5
  77. package/dist/schema/Config/Transform.js +51 -0
  78. package/dist/schema/Config/Transform.js.map +1 -0
  79. package/dist/schema/Defaults.d.ts +20 -0
  80. package/dist/schema/Defaults.js +24 -0
  81. package/dist/schema/Defaults.js.map +1 -0
  82. package/dist/schema/ImportMap.d.ts +30 -0
  83. package/dist/schema/ImportMap.js +28 -0
  84. package/dist/schema/ImportMap.js.map +1 -0
  85. package/{build → dist}/schema/TSConfig.d.ts +23 -9
  86. package/dist/schema/TSConfig.js +39 -0
  87. package/dist/schema/TSConfig.js.map +1 -0
  88. package/{build → dist}/schema/schema.d.ts +11 -2
  89. package/{build → dist}/schema/schema.js +11 -2
  90. package/dist/schema/schema.js.map +1 -0
  91. package/dist/task/Command.d.ts +287 -0
  92. package/dist/task/Command.js +404 -0
  93. package/dist/task/Command.js.map +1 -0
  94. package/dist/task/Group.d.ts +15 -0
  95. package/dist/task/Group.js +29 -0
  96. package/dist/task/Group.js.map +1 -0
  97. package/dist/task/OutputPolicy.d.ts +262 -0
  98. package/dist/task/OutputPolicy.js +364 -0
  99. package/dist/task/OutputPolicy.js.map +1 -0
  100. package/dist/task/Task.d.ts +210 -0
  101. package/dist/task/Task.js +312 -0
  102. package/dist/task/Task.js.map +1 -0
  103. package/package.json +13 -10
  104. package/.gitignore +0 -7
  105. package/build/cli/DepFLowCLI.d.ts +0 -16
  106. package/build/cli/DepFLowCLI.js +0 -254
  107. package/build/cli/DepFLowCLI.js.map +0 -1
  108. package/build/cli/bin.js +0 -38
  109. package/build/cli/bin.js.map +0 -1
  110. package/build/config/Config.d.ts +0 -28
  111. package/build/config/Config.js +0 -46
  112. package/build/config/Config.js.map +0 -1
  113. package/build/config/ImportMap.d.ts +0 -51
  114. package/build/config/ImportMap.js +0 -97
  115. package/build/config/ImportMap.js.map +0 -1
  116. package/build/config/TSConfig.d.ts +0 -54
  117. package/build/config/TSConfig.js +0 -104
  118. package/build/config/TSConfig.js.map +0 -1
  119. package/build/schema/Config/Builder.js +0 -48
  120. package/build/schema/Config/Builder.js.map +0 -1
  121. package/build/schema/Config/Config.js +0 -20
  122. package/build/schema/Config/Config.js.map +0 -1
  123. package/build/schema/Config/Dependency.js +0 -25
  124. package/build/schema/Config/Dependency.js.map +0 -1
  125. package/build/schema/Config/Extractor.js +0 -25
  126. package/build/schema/Config/Extractor.js.map +0 -1
  127. package/build/schema/Config/Resolver.js +0 -25
  128. package/build/schema/Config/Resolver.js.map +0 -1
  129. package/build/schema/Config/Transform.js +0 -27
  130. package/build/schema/Config/Transform.js.map +0 -1
  131. package/build/schema/ImportMap.d.ts +0 -22
  132. package/build/schema/ImportMap.js +0 -12
  133. package/build/schema/ImportMap.js.map +0 -1
  134. package/build/schema/TSConfig.js +0 -19
  135. package/build/schema/TSConfig.js.map +0 -1
  136. package/build/schema/schema.js.map +0 -1
  137. package/build/support/Builder/Builder.d.ts +0 -46
  138. package/build/support/Builder/Builder.js +0 -116
  139. package/build/support/Builder/Builder.js.map +0 -1
  140. package/build/support/Dependency/Dependency.d.ts +0 -38
  141. package/build/support/Dependency/Dependency.js +0 -14
  142. package/build/support/Dependency/Dependency.js.map +0 -1
  143. package/build/support/Dependency/GitDependency.d.ts +0 -20
  144. package/build/support/Dependency/GitDependency.js +0 -67
  145. package/build/support/Dependency/GitDependency.js.map +0 -1
  146. package/build/support/Dependency/NpmDependency.d.ts +0 -18
  147. package/build/support/Dependency/NpmDependency.js +0 -65
  148. package/build/support/Dependency/NpmDependency.js.map +0 -1
  149. package/build/support/Git.d.ts +0 -53
  150. package/build/support/Git.js +0 -86
  151. package/build/support/Git.js.map +0 -1
  152. package/build/support/PathResolver/AliasCompiler.js.map +0 -1
  153. package/build/support/PathResolver/PathResolver.js +0 -105
  154. package/build/support/PathResolver/PathResolver.js.map +0 -1
  155. package/build/support/PathResolver/PathRewriter.d.ts +0 -18
  156. package/build/support/PathResolver/PathRewriter.js.map +0 -1
  157. package/build/support/PathResolver/Utils.d.ts +0 -36
  158. package/build/support/PathResolver/Utils.js +0 -45
  159. package/build/support/PathResolver/Utils.js.map +0 -1
  160. package/build/support/Task/Command.d.ts +0 -49
  161. package/build/support/Task/Command.js +0 -100
  162. package/build/support/Task/Command.js.map +0 -1
  163. package/build/support/Task/Task.d.ts +0 -84
  164. package/build/support/Task/Task.js +0 -145
  165. package/build/support/Task/Task.js.map +0 -1
  166. package/build/support/Utils.d.ts +0 -40
  167. package/build/support/Utils.js +0 -138
  168. package/build/support/Utils.js.map +0 -1
  169. package/build/support/Validator.d.ts +0 -22
  170. package/build/support/Validator.js +0 -28
  171. package/build/support/Validator.js.map +0 -1
  172. /package/{build → dist}/cli/bin.d.ts +0 -0
@@ -0,0 +1,391 @@
1
+ /**
2
+ * @author NetFeez <netfeez.dev@gmail.com>.
3
+ * @description Runs dependency build pipelines: shell commands, file extraction and content transformations.
4
+ * @license Apache-2.0
5
+ */
6
+ import { File, Path } from "@netfeez/common-node";
7
+ import Task from "../task/Task.js";
8
+ import Group from "../task/Group.js";
9
+ export class Builder {
10
+ pipeline;
11
+ cwd;
12
+ projectRoot;
13
+ logger;
14
+ policy;
15
+ /** The step that stopped the pipeline, or `null` while it is still walking it. */
16
+ vStopped = null;
17
+ constructor(info) {
18
+ this.pipeline = info.pipeline;
19
+ this.cwd = info.cwd;
20
+ this.projectRoot = info.projectRoot;
21
+ this.logger = info.logger || null;
22
+ this.policy = info.policy || null;
23
+ }
24
+ /**
25
+ * Runs the pipeline and reports what every step of it did.
26
+ * @returns A promise resolving with the report of the run, or rejecting with a
27
+ * {@link Builder.Failure} carrying that same report, when a step stopped the pipeline.
28
+ *
29
+ * @remarks The report is the verdict of the run, and it is produced whether the run succeeded or
30
+ * failed: a caller that catches a {@link Builder.Failure} gets the steps that ran before the one
31
+ * that stopped it, and the steps that never ran at all, so nothing about the pipeline is missing
32
+ * from a failure.
33
+ *
34
+ * @remarks The group of the run is closed in a `finally`, so the steps of a pipeline that threw leave
35
+ * the output as closed as the ones of a pipeline that finished. It is opened only when the run
36
+ * decorates its output, because a group that draws nothing still leaves a box and an indentation
37
+ * around every line written inside it.
38
+ */
39
+ async run() {
40
+ const boxed = this.policy === null || this.policy.decoration === 'on';
41
+ if (boxed)
42
+ this.logger?.group(Group.create('#00FFB4'));
43
+ try {
44
+ const steps = await this.walk();
45
+ const report = Builder.report(steps);
46
+ this.policy?.settleBuild(report);
47
+ if (!report.ok)
48
+ throw new Builder.Failure(report, Builder.reason(report));
49
+ return report;
50
+ }
51
+ finally {
52
+ if (boxed)
53
+ this.logger?.end();
54
+ }
55
+ }
56
+ /**
57
+ * Walks the pipeline in order, running each step until one of them stops it.
58
+ * @returns A promise resolving with one report per step of the pipeline, the ones that ran and the
59
+ * ones the stop left behind.
60
+ */
61
+ async walk() {
62
+ const steps = [];
63
+ for (const [position, entry] of this.pipeline.entries()) {
64
+ const index = position + 1;
65
+ if (this.vStopped)
66
+ steps.push(Builder.pending(index, Builder.kind(entry)));
67
+ else
68
+ steps.push(await this.runStep(index, entry));
69
+ }
70
+ return steps;
71
+ }
72
+ /**
73
+ * Runs one step of the pipeline and turns it into its report.
74
+ * @param index - The position of the step inside the pipeline, starting at 1.
75
+ * @param entry - The entry of the pipeline describing the step.
76
+ * @returns A promise resolving with the report of the step.
77
+ *
78
+ * @remarks An entry that carries no step at all is reported as one that did not run, the way the
79
+ * pipeline has always walked over it, and the report accounts for it all the same.
80
+ */
81
+ async runStep(index, entry) {
82
+ if ('run' in entry && entry.run)
83
+ return this.runRun(index, entry);
84
+ if ('extract' in entry && entry.extract)
85
+ await this.runExtractor(entry.extract);
86
+ else if ('transform' in entry && entry.transform)
87
+ await this.runGlobalTransform(entry.transform);
88
+ else
89
+ return Builder.pending(index, null);
90
+ return Builder.settled(index, 'extract' in entry ? 'extract' : 'transform');
91
+ }
92
+ /**
93
+ * Runs the commands of a `run` step as a Task, settling the step with the verdict of the task.
94
+ * @param index - The position of the step inside the pipeline, starting at 1.
95
+ * @param entry - The `run` entry describing the step.
96
+ * @returns A promise resolving with the report of the step.
97
+ *
98
+ * @remarks A step that does not tolerate its failures stops the pipeline, so the steps after it are
99
+ * reported as steps that never ran. The step itself is not rethrown from here: the report of the run
100
+ * is the verdict of the pipeline, and rejecting twice would report the same failure twice.
101
+ */
102
+ async runRun(index, entry) {
103
+ const commands = typeof entry.run === 'string' ? [entry.run] : entry.run;
104
+ const identity = Builder.identity(index, this.steps);
105
+ try {
106
+ const outcome = await this.runTask(commands, this.cwd, { maxTimeMs: entry.maxTimeMs, allowFails: entry.allowFails }, identity);
107
+ return {
108
+ index,
109
+ kind: 'run',
110
+ ran: true,
111
+ success: outcome.success,
112
+ failed: outcome.fails,
113
+ tolerated: entry.allowFails === true && outcome.fails > 0,
114
+ reason: null,
115
+ commands: outcome.results.map(Builder.commandReport)
116
+ };
117
+ }
118
+ catch (failure) {
119
+ const outcome = failure instanceof Task.Failure ? failure.outcome : null;
120
+ this.vStopped = { index, reason: failure instanceof Task.Failure ? failure.reason : 'step' };
121
+ if (failure instanceof Task.Failure)
122
+ this.policy?.stepFailed(identity, failure);
123
+ return {
124
+ index,
125
+ kind: 'run',
126
+ ran: true,
127
+ success: false,
128
+ failed: outcome?.fails ?? 0,
129
+ tolerated: false,
130
+ reason: this.vStopped.reason,
131
+ commands: (outcome?.results ?? []).map(Builder.commandReport)
132
+ };
133
+ }
134
+ }
135
+ /**
136
+ * How many steps of the pipeline run commands, the number a command identity is qualified by.
137
+ * @returns The amount of `run` entries in the pipeline.
138
+ */
139
+ get steps() {
140
+ return this.pipeline.filter(entry => Builder.kind(entry) === 'run').length;
141
+ }
142
+ /**
143
+ * Runs the shell commands of a build step as a Task, reporting them through the policy of the run.
144
+ * The verdict of the task is the verdict of the step: it is awaited, never read from an event.
145
+ * @param commands - The shell commands to run, in order.
146
+ * @param cwd - The working directory the commands run in.
147
+ * @param options - The options of the step: its deadline and whether its failures are tolerated.
148
+ * @param identity - The identity the commands of this task are reported under.
149
+ * @returns A promise resolving with the summary of the run of the task.
150
+ * @throws { Task.Failure } When the step fails and does not tolerate failures.
151
+ */
152
+ async runTask(commands, cwd, options, identity) {
153
+ const task = new Task(cwd, commands, options);
154
+ if (this.policy) {
155
+ task.on('line', (line, ordinal) => this.policy?.live(identity, line, ordinal, 'stdout'));
156
+ task.on('err', (line, ordinal) => this.policy?.live(identity, line, ordinal, 'stderr'));
157
+ task.once('finish', (data) => this.policy?.settleTask(identity, data));
158
+ }
159
+ else if (this.logger) {
160
+ task.on('line', (line) => this.logger?.info(`${line}`));
161
+ task.on('err', (line) => this.logger?.error(`${line}`));
162
+ }
163
+ return task.run();
164
+ }
165
+ /**
166
+ * Applies a global transformation to every file of the working directory, the one the configuration
167
+ * asks for through its glob.
168
+ * @param options - The transformation to apply, either as a search and replace pair or as a plain
169
+ * regular expression.
170
+ * @returns A promise resolving when every file of the glob has been transformed.
171
+ */
172
+ async runGlobalTransform(options) {
173
+ this.logger?.log(`&C7Applying global transformation in &C3${this.cwd}&C7...`);
174
+ const transformAction = Builder.replacer(options);
175
+ const glob = options.glob;
176
+ await File.smartProcess(glob, this.cwd, {
177
+ cwd: this.cwd,
178
+ }, async ({ src, dest }) => {
179
+ const content = await File.read(src);
180
+ const transformedContent = transformAction(content);
181
+ await File.write(dest, transformedContent);
182
+ });
183
+ }
184
+ /**
185
+ * Resolves the destination folder of an extraction entry, which is relative to the project root, and
186
+ * guarantees it stays inside it.
187
+ * @param to - The destination folder declared by the entry.
188
+ * @returns The normalized path of the destination folder.
189
+ * @throws { Error } When a relative destination escapes the project root.
190
+ *
191
+ * @remarks An absolute destination is taken as it stands: writing outside the project is a decision
192
+ * the configuration takes on purpose, and spelling it out as an absolute path is what makes it one.
193
+ * A relative destination cannot, because a `..` that walks out of the project is a mistake and not a
194
+ * decision. The project root is a destination like any other, so it is not treated as an escape.
195
+ */
196
+ resolveDestination(to) {
197
+ if (Path.isAbsolute(to))
198
+ return to;
199
+ const root = Path.normalize(this.projectRoot);
200
+ const destination = Path.normalize(Path.join(root, to));
201
+ if (destination !== root && !Path.isInside(root, destination))
202
+ throw new Error(`Extraction destination resolves outside of the project root: ${destination}`);
203
+ return destination;
204
+ }
205
+ /**
206
+ * Runs the extraction process based on the provided entry configuration, which can be either a string or an array of extraction entries.
207
+ * It handles the copying of files from the specified source to the target location, applying any necessary path transformations based on the provided replacer configuration.
208
+ * This method is essential for managing the file extraction phase of the build process, allowing for flexible and customizable file handling as defined in the builder configuration.
209
+ * @param entry - A string or an array of extraction entries that define the source, target, and optional path transformation for the extraction process.
210
+ * @returns A promise that resolves when the extraction process is complete, or rejects with an error if any issues occur during the file copying or transformation.
211
+ * @throws Will throw an error if any issues occur during the file copying process, such as problems with reading or writing files, or if the provided entry configuration is invalid.
212
+ */
213
+ async runExtractor(entry) {
214
+ const extractor = typeof entry === 'string'
215
+ ? { '**/*': { to: entry } }
216
+ : entry;
217
+ for (const [from, entry] of Object.entries(extractor)) {
218
+ const { to, map, transform } = typeof entry === 'string' ? { to: entry } : entry;
219
+ const mapper = Builder.replacer(map);
220
+ const replacer = Builder.replacer(transform);
221
+ const destination = this.resolveDestination(to);
222
+ this.logger?.log(`&C7Extracting &C3${from}&C7 to &C3${to}&C7...`);
223
+ await File.smartProcess(from, destination, {
224
+ cwd: this.cwd,
225
+ map: mapper,
226
+ }, async ({ src, dest }) => {
227
+ const content = await File.read(src);
228
+ const transformedContent = replacer(content);
229
+ await File.write(dest, transformedContent);
230
+ });
231
+ }
232
+ }
233
+ /**
234
+ * Creates a string replacement function based on the provided replacer configuration, which can be either a simple string or an object defining a search pattern and replacement string. This method is used to generate a function that can be applied to strings for dynamic transformations during the build process, allowing for flexible and customizable string manipulation as defined in the builder configuration.
235
+ * @param replacer - A configuration for string replacement, which can be either a string (used as a regex pattern) or an object containing a search pattern and replacement string.
236
+ * @returns A function that takes a string as input and returns a new string with the specified replacements applied, based on the provided replacer configuration.
237
+ * @throws Will throw an error if the provided replacer configuration is invalid, such as if it is neither a string nor an object with the required properties.
238
+ */
239
+ static replacer(replacer) {
240
+ if (typeof replacer === 'string') {
241
+ const search = new RegExp(replacer, 'g');
242
+ return (str) => str.replace(search, '');
243
+ }
244
+ else if (replacer !== null && typeof replacer === 'object') {
245
+ const flags = replacer.flags || 'g';
246
+ const search = new RegExp(replacer.search, flags);
247
+ const replace = replacer.replace || '';
248
+ return (str) => str.replace(search, replace);
249
+ }
250
+ else
251
+ return (str) => str;
252
+ }
253
+ /**
254
+ * The kind of step an entry of the pipeline describes, decided by the key it carries.
255
+ * @param entry - The entry of the pipeline.
256
+ * @returns The kind of the step, or `null` when the entry describes no step at all.
257
+ */
258
+ static kind(entry) {
259
+ if ('run' in entry && entry.run)
260
+ return 'run';
261
+ if ('extract' in entry && entry.extract)
262
+ return 'extract';
263
+ if ('transform' in entry && entry.transform)
264
+ return 'transform';
265
+ return null;
266
+ }
267
+ /**
268
+ * The identity the commands of a `run` step are reported under.
269
+ *
270
+ * @remarks A command is identified as `C<M>` inside its own task, and as `S<N> · C<M>` when the
271
+ * pipeline runs more than one of them: with a single `run` step there is nothing to qualify it
272
+ * against, and with more than one there is, so `C1` alone would name two different commands.
273
+ *
274
+ * @param index - The position of the step inside the pipeline, starting at 1.
275
+ * @param steps - How many `run` steps the pipeline has.
276
+ * @returns The identity of the commands of the step.
277
+ */
278
+ static identity(index, steps) {
279
+ return { step: steps > 1 ? index : null };
280
+ }
281
+ /**
282
+ * The report of a command inside a step: who it was and how it ended, without what it printed.
283
+ *
284
+ * @remarks The output of a command is not part of the report: a report says what the pipeline did,
285
+ * and a build that printed a log would carry that log in every summary it produced, in every layer
286
+ * that received it. The output stays where it was produced, in the results of the task, and it is
287
+ * read once, when the task settles.
288
+ *
289
+ * @param result - The result of the command.
290
+ * @returns The report of the command.
291
+ */
292
+ static commandReport(result) {
293
+ return {
294
+ ordinal: result.ordinal,
295
+ label: result.label,
296
+ success: result.success,
297
+ code: result.code,
298
+ signal: result.signal,
299
+ reason: result.reason,
300
+ time: result.time
301
+ };
302
+ }
303
+ /**
304
+ * The report of a step that ran and had nothing to report beyond having run.
305
+ * @param index - The position of the step inside the pipeline, starting at 1.
306
+ * @param kind - The kind of the step, which a step that only works on files never has.
307
+ * @returns The report of the step.
308
+ */
309
+ static settled(index, kind) {
310
+ return { index, kind, ran: true, success: true, failed: 0, tolerated: false, reason: null, commands: [] };
311
+ }
312
+ /**
313
+ * The report of a step that never ran, either because an earlier one stopped the pipeline or because
314
+ * the entry describes no step at all.
315
+ * @param index - The position of the step inside the pipeline, starting at 1.
316
+ * @param kind - The kind of the step, `null` when the entry describes none.
317
+ * @returns The report of the step that did not run.
318
+ */
319
+ static pending(index, kind) {
320
+ return { index, kind, ran: false, success: false, failed: 0, tolerated: false, reason: null, commands: [] };
321
+ }
322
+ /**
323
+ * The report of a whole pipeline.
324
+ * @param steps - One report per step of the pipeline, in order.
325
+ * @returns The report of the run.
326
+ */
327
+ static report(steps) {
328
+ const ran = steps.filter(step => step.ran);
329
+ return {
330
+ ok: ran.length === steps.length && ran.every(step => step.success),
331
+ commands: ran.reduce((total, step) => total + step.commands.length, 0),
332
+ failed: ran.reduce((total, step) => total + step.failed, 0),
333
+ tolerated: ran.filter(step => step.tolerated).reduce((total, step) => total + step.failed, 0),
334
+ steps
335
+ };
336
+ }
337
+ /**
338
+ * Why the pipeline stopped, read from the step that stopped it: the reason the step could not
339
+ * complete, or the commands that failed and it did not tolerate.
340
+ * @param report - The report of the run.
341
+ * @returns The reason the run did not finish successfully.
342
+ */
343
+ static reason(report) {
344
+ const step = report.steps.find(entry => entry.ran && !entry.success);
345
+ if (!step)
346
+ return 'step';
347
+ if (step.reason !== null)
348
+ return step.reason;
349
+ return step.failed > 0 ? 'command' : 'step';
350
+ }
351
+ }
352
+ (function (Builder) {
353
+ /**
354
+ * The failure of a pipeline, carrying the report of the run that produced it.
355
+ *
356
+ * @remarks The report is the same one the run would have resolved with, so a caller that only wants
357
+ * to know how the pipeline went catches this and reads it instead of rebuilding it from the steps
358
+ * that did run.
359
+ */
360
+ class Failure extends Error {
361
+ report;
362
+ reason;
363
+ /**
364
+ * Creates the failure of a pipeline.
365
+ * @param report - The report of the run.
366
+ * @param reason - Why the pipeline stopped.
367
+ */
368
+ constructor(report, reason = 'step') {
369
+ super(Failure.message(report, reason));
370
+ this.report = report;
371
+ this.reason = reason;
372
+ this.name = 'Builder.Failure';
373
+ }
374
+ /**
375
+ * The message describing which step stopped the pipeline and why, in one line.
376
+ * @param report - The report of the run.
377
+ * @param reason - Why the pipeline stopped.
378
+ * @returns The message of the failure.
379
+ */
380
+ static message(report, reason) {
381
+ const step = report.steps.find(entry => entry.ran && !entry.success);
382
+ const where = step ? `Step ${step.index}` : 'The pipeline';
383
+ const because = reason === 'command' ? `${report.failed} failed command(s)`
384
+ : reason === 'step' ? 'a step of it failed' : reason;
385
+ return `${where} stopped the pipeline: ${because}.`;
386
+ }
387
+ }
388
+ Builder.Failure = Failure;
389
+ })(Builder || (Builder = {}));
390
+ export default Builder;
391
+ //# sourceMappingURL=Builder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Builder.js","sourceRoot":"","sources":["../../src/builder/Builder.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,157 @@
1
+ /**
2
+ * @author NetFeez <netfeez.dev@gmail.com>.
3
+ * @description The console interface the CLI is built on: it reads a command, runs it and answers it,
4
+ * and it draws the help the global flags and the arguments of every command are told in.
5
+ * @license Apache-2.0
6
+ */
7
+ import type { Engine, ConsoleTransport } from '@netfeez/vterm';
8
+ import type Flags from './Flags.js';
9
+ export declare class CLI {
10
+ /** What reads the input of the console interface. */
11
+ protected dataHandleInstance: CLI.dataHandler;
12
+ /** What is written before every command the interface reads. */
13
+ prompt: string;
14
+ /** The input the interface reads commands from. */
15
+ in: NodeJS.ReadStream;
16
+ /** The engine the interface answers through. */
17
+ out: Engine;
18
+ /** The commands the interface accepts, keyed by the name each one is invoked with. */
19
+ commandMap: CLI.CommandMap;
20
+ /** The terminal the prompt and the help are written to. */
21
+ protected console: ConsoleTransport;
22
+ /** The flags that are not specific to a command, keyed by the name each one is declared under. */
23
+ protected globals: Flags.Declaration;
24
+ /** The branded line the help opens with. */
25
+ protected title: string;
26
+ /**
27
+ * Wires a console interface to its terminal, its global flags and its commands.
28
+ * @param globals - The flags no command owns, declared as `Flags` declares them.
29
+ * @param config - How the interface presents itself: the name of its runs, its prompt and its title.
30
+ */
31
+ constructor(globals?: Flags.Declaration, config?: CLI.Config);
32
+ /** Starts reading what is written to the input. **/
33
+ protected startReadIn(): void;
34
+ /** Stops reading what is written to the input. **/
35
+ protected stopReadIn(): void;
36
+ /** Starts the console UI. **/
37
+ start(): void;
38
+ /** Stops the console UI. **/
39
+ stop(): void;
40
+ /**
41
+ * Runs the command the input carries, and writes the prompt again unless the command leaves.
42
+ * @param data - What arrived in the input.
43
+ * @returns A promise of the command being over.
44
+ */
45
+ protected dataHandler(data: Buffer): Promise<void>;
46
+ /**
47
+ * The command of that name, when the map carries one.
48
+ * @param command - The name of the command.
49
+ * @returns The command, or undefined when the map carries no command of that name.
50
+ */
51
+ getCommand(command: string): CLI.Command | undefined;
52
+ /**
53
+ * Puts a command in the map.
54
+ * @param command - The name of the command.
55
+ * @param exec - What the command does when it is written.
56
+ * @param info - What `help` tells about it, the arguments it accepts among it.
57
+ * @returns This instance, so commands can be added one after another.
58
+ */
59
+ addCommand(command: string, exec: CLI.commandExec, info?: CLI.CommandInfo): this;
60
+ /**
61
+ * Takes a command out of the map.
62
+ * @param command - The name of the command.
63
+ * @returns This instance, so commands can be removed one after another.
64
+ */
65
+ removeCommand(command: string): this;
66
+ /**
67
+ * Puts the commands every console interface carries in the map.
68
+ **/
69
+ protected addDefaultCommands(): void;
70
+ /**
71
+ * Writes the banner, the global flags and every command of the map with its usage, its description
72
+ * and the arguments it accepts.
73
+ *
74
+ * @remarks The help belongs to the terminal and not to a run, so it is written as it is composed
75
+ * and it is not announced through the engine: no timestamp, level or name is put in front of it,
76
+ * and a line is only broken where this method breaks it.
77
+ **/
78
+ protected showHelp(): void;
79
+ /**
80
+ * The name of a flag as the help writes it, with the aliases it accepts and the value it takes.
81
+ * @param name - The name the flag is declared under.
82
+ * @param flag - The declared flag.
83
+ * @returns The name of the flag, colored.
84
+ */
85
+ protected static flagKey(name: string, flag: Flags.Flag): string;
86
+ /**
87
+ * The name of an argument as the help writes it, telling an optional one and a variadic one apart.
88
+ * @param name - The name the argument is declared under.
89
+ * @param argument - The declared argument.
90
+ * @returns The name of the argument, colored.
91
+ */
92
+ protected static argumentKey(name: string, argument: CLI.Argument): string;
93
+ /**
94
+ * Lays out a name and what it is for in the columns left after the name.
95
+ * @param key - The name, with the tokens that color it.
96
+ * @param description - What the name is for.
97
+ * @param width - The visible width every line is kept within.
98
+ * @param indent - The visible columns the entry starts at.
99
+ * @returns The lines of the entry, the description broken in as many lines as it needs.
100
+ */
101
+ protected static describe(key: string, description: string, width: number, indent?: number): string[];
102
+ /**
103
+ * Breaks a text in as many lines as it needs to fit a visible width, on its word boundaries.
104
+ * @param text - The text to break, without tokens in it.
105
+ * @param width - The visible width every line is kept within.
106
+ * @returns The lines the text was broken in.
107
+ */
108
+ protected static wrap(text: string, width: number): string[];
109
+ /**
110
+ * The columns a text paints, with its tokens taken out.
111
+ * @param text - The text to measure, with the tokens of the grammar in it.
112
+ * @returns The number of visible columns it paints.
113
+ */
114
+ protected static visibleWidth(text: string): number;
115
+ }
116
+ export declare namespace CLI {
117
+ type dataHandler = (data: Buffer) => void;
118
+ type commandExec = (this: CLI, command: string, args: string[]) => Promise<void> | void;
119
+ /** A positional argument a command accepts. **/
120
+ interface Argument {
121
+ /** What the argument is for. **/
122
+ description: string;
123
+ /** Whether the command cannot run without it. Defaults to `true`. **/
124
+ required?: boolean;
125
+ /** Whether the argument takes every token that follows, written with a trailing ellipsis. **/
126
+ variadic?: boolean;
127
+ }
128
+ /** The positional arguments a command accepts, keyed by the name each one is declared under. **/
129
+ type Arguments = {
130
+ readonly [name: string]: Argument;
131
+ };
132
+ /** What `help` tells about a command. **/
133
+ interface CommandInfo {
134
+ description?: string;
135
+ usage?: string;
136
+ args?: Arguments;
137
+ }
138
+ /** A command of the console interface, with what it does and what `help` tells about it. **/
139
+ interface Command extends CommandInfo {
140
+ name: string;
141
+ exec: commandExec;
142
+ }
143
+ /** The commands of the interface, keyed by the name each one is invoked with. **/
144
+ interface CommandMap {
145
+ [command: string]: Command;
146
+ }
147
+ /** How the console interface presents itself. **/
148
+ interface Config {
149
+ /** The name every run of the interface is written with. **/
150
+ name?: string;
151
+ /** The prompt written before every command, with the tokens of the console grammar. **/
152
+ prompt?: string;
153
+ /** The branded line the help opens with, with the tokens of the console grammar. **/
154
+ title?: string;
155
+ }
156
+ }
157
+ export default CLI;