|
| 1 | +/** |
| 2 | + * @license |
| 3 | + * Copyright Google Inc. All Rights Reserved. |
| 4 | + * |
| 5 | + * Use of this source code is governed by an MIT-style license that can be |
| 6 | + * found in the LICENSE file at https://angular.io/license |
| 7 | + */ |
| 8 | +import { experimental, json, logging } from '@angular-devkit/core'; |
| 9 | +import { Observable } from 'rxjs'; |
| 10 | +import { Schema as RealBuilderInput, Target as RealTarget } from './input-schema'; |
| 11 | +import { Schema as RealBuilderOutput } from './output-schema'; |
| 12 | +import { Schema as RealBuilderProgress, State as BuilderProgressState } from './progress-schema'; |
| 13 | + |
| 14 | +export type Target = json.JsonObject & RealTarget; |
| 15 | +export { |
| 16 | + BuilderProgressState, |
| 17 | +}; |
| 18 | + |
| 19 | +// Type short hands. |
| 20 | +export type BuilderRegistry = |
| 21 | + experimental.jobs.Registry<json.JsonObject, BuilderInput, BuilderOutput>; |
| 22 | + |
| 23 | + |
| 24 | +/** |
| 25 | + * An API typed BuilderProgress. The interface generated from the schema is too permissive, |
| 26 | + * so this API is the one we show in our API. Please note that not all fields are in there; this |
| 27 | + * is in addition to fields in the schema. |
| 28 | + */ |
| 29 | +export type TypedBuilderProgress = ( |
| 30 | + { state: BuilderProgressState.Stopped; } |
| 31 | + | { state: BuilderProgressState.Error; error: json.JsonValue; } |
| 32 | + | { state: BuilderProgressState.Waiting; status?: string; } |
| 33 | + | { state: BuilderProgressState.Running; status?: string; current: number; total?: number; } |
| 34 | +); |
| 35 | + |
| 36 | +/** |
| 37 | + * Declaration of those types as JsonObject compatible. JsonObject is not compatible with |
| 38 | + * optional members, so those wouldn't be directly assignable to our internal Json typings. |
| 39 | + * Forcing the type to be both a JsonObject and the type from the Schema tells Typescript they |
| 40 | + * are compatible (which they are). |
| 41 | + * These types should be used everywhere. |
| 42 | + */ |
| 43 | +export type BuilderInput = json.JsonObject & RealBuilderInput; |
| 44 | +export type BuilderOutput = json.JsonObject & RealBuilderOutput; |
| 45 | +export type BuilderProgress = json.JsonObject & RealBuilderProgress & TypedBuilderProgress; |
| 46 | + |
| 47 | +/** |
| 48 | + * A progress report is what the tooling will receive. It contains the builder info and the target. |
| 49 | + * Although these are serializable, they are only exposed through the tooling interface, not the |
| 50 | + * builder interface. The watch dog sends BuilderProgress and the Builder has a set of functions |
| 51 | + * to manage the state. |
| 52 | + */ |
| 53 | +export type BuilderProgressReport = BuilderProgress & ({ |
| 54 | + target?: Target; |
| 55 | + builder: BuilderInfo; |
| 56 | +}); |
| 57 | + |
| 58 | +/** |
| 59 | + * A Run, which is what is returned by scheduleBuilder or scheduleTarget functions. This should |
| 60 | + * be reconstructed across memory boundaries (it's not serializable but all internal information |
| 61 | + * are). |
| 62 | + */ |
| 63 | +export interface BuilderRun { |
| 64 | + /** |
| 65 | + * Unique amongst runs. This is the same ID as the context generated for the run. It can be |
| 66 | + * used to identify multiple unique runs. There is no guarantee that a run is a single output; |
| 67 | + * a builder can rebuild on its own and will generate multiple outputs. |
| 68 | + */ |
| 69 | + id: number; |
| 70 | + |
| 71 | + /** |
| 72 | + * The builder information. |
| 73 | + */ |
| 74 | + info: BuilderInfo; |
| 75 | + |
| 76 | + /** |
| 77 | + * The next output from a builder. This is recommended when scheduling a builder and only being |
| 78 | + * interested in the result of that single run, not of a watch-mode builder. |
| 79 | + */ |
| 80 | + result: Promise<BuilderOutput>; |
| 81 | + |
| 82 | + /** |
| 83 | + * The output(s) from the builder. A builder can have multiple outputs. |
| 84 | + * This always replay the last output when subscribed. |
| 85 | + */ |
| 86 | + output: Observable<BuilderOutput>; |
| 87 | + |
| 88 | + /** |
| 89 | + * The progress report. A progress also contains an ID, which can be different than this run's |
| 90 | + * ID (if the builder calls scheduleBuilder or scheduleTarget). |
| 91 | + * This will always replay the last progress on new subscriptions. |
| 92 | + */ |
| 93 | + progress: Observable<BuilderProgressReport>; |
| 94 | + |
| 95 | + /** |
| 96 | + * Stop the builder from running. Returns a promise that resolves when the builder is stopped. |
| 97 | + * Some builders might not handle stopping properly and should have a timeout here. |
| 98 | + */ |
| 99 | + stop(): Promise<void>; |
| 100 | +} |
| 101 | + |
| 102 | +/** |
| 103 | + * The context received as a second argument in your builder. |
| 104 | + */ |
| 105 | +export interface BuilderContext { |
| 106 | + /** |
| 107 | + * Unique amongst contexts. Contexts instances are not guaranteed to be the same (but it could |
| 108 | + * be the same context), and all the fields in a context could be the same, yet the builder's |
| 109 | + * context could be different. This is the same ID as the corresponding run. |
| 110 | + */ |
| 111 | + id: number; |
| 112 | + |
| 113 | + /** |
| 114 | + * The builder info that called your function. Since the builder info is from the builder.json |
| 115 | + * (or the host), it could contain information that is different than expected. |
| 116 | + */ |
| 117 | + builder: BuilderInfo; |
| 118 | + |
| 119 | + /** |
| 120 | + * A logger that appends messages to a log. This could be a separate interface or completely |
| 121 | + * ignored. `console.log` could also be completely ignored. |
| 122 | + */ |
| 123 | + logger: logging.LoggerApi; |
| 124 | + |
| 125 | + /** |
| 126 | + * The absolute workspace root of this run. This is a system path and will not be normalized; |
| 127 | + * ie. on Windows it will starts with `C:\\` (or whatever drive). |
| 128 | + */ |
| 129 | + workspaceRoot: string; |
| 130 | + |
| 131 | + /** |
| 132 | + * The current directory the user is in. This could be outside the workspace root. This is a |
| 133 | + * system path and will not be normalized; ie. on Windows it will starts with `C:\\` (or |
| 134 | + * whatever drive). |
| 135 | + */ |
| 136 | + currentDirectory: string; |
| 137 | + |
| 138 | + /** |
| 139 | + * The target that was used to run this builder. |
| 140 | + * Target is optional if a builder was ran using `scheduleBuilder()`. |
| 141 | + */ |
| 142 | + target?: Target; |
| 143 | + |
| 144 | + /** |
| 145 | + * Schedule a target in the same workspace. This can be the same target that is being executed |
| 146 | + * right now, but targets of the same name are serialized. |
| 147 | + * Running the same target and waiting for it to end will result in a deadlocking scenario. |
| 148 | + * Targets are considered the same if the project, the target AND the configuration are the same. |
| 149 | + * @param target The target to schedule. |
| 150 | + * @param overrides A set of options to override the workspace set of options. |
| 151 | + * @return A promise of a run. It will resolve when all the members of the run are available. |
| 152 | + */ |
| 153 | + scheduleTarget( |
| 154 | + target: Target, |
| 155 | + overrides?: json.JsonObject, |
| 156 | + ): Promise<BuilderRun>; |
| 157 | + |
| 158 | + /** |
| 159 | + * Schedule a builder by its name. This can be the same builder that is being executed. |
| 160 | + * @param builderName The name of the builder, ie. its `packageName:builderName` tuple. |
| 161 | + * @param options All options to use for the builder (by default empty object). There is no |
| 162 | + * additional options added, e.g. from the workspace. |
| 163 | + * @return A promise of a run. It will resolve when all the members of the run are available. |
| 164 | + */ |
| 165 | + scheduleBuilder( |
| 166 | + builderName: string, |
| 167 | + options?: json.JsonObject, |
| 168 | + ): Promise<BuilderRun>; |
| 169 | + |
| 170 | + /** |
| 171 | + * Set the builder to running. This should be used if an external event triggered a re-run, |
| 172 | + * e.g. a file watched was changed. |
| 173 | + */ |
| 174 | + reportRunning(): void; |
| 175 | + |
| 176 | + /** |
| 177 | + * Update the status string shown on the interface. |
| 178 | + * @param status The status to set it to. An empty string can be used to remove the status. |
| 179 | + */ |
| 180 | + reportStatus(status: string): void; |
| 181 | + |
| 182 | + /** |
| 183 | + * Update the progress for this builder run. |
| 184 | + * @param current The current progress. This will be between 0 and total. |
| 185 | + * @param total A new total to set. By default at the start of a run this is 1. If omitted it |
| 186 | + * will use the same value as the last total. |
| 187 | + * @param status Update the status string. If omitted the status string is not modified. |
| 188 | + */ |
| 189 | + reportProgress(current: number, total?: number, status?: string): void; |
| 190 | +} |
| 191 | + |
| 192 | + |
| 193 | +/** |
| 194 | + * An accepted return value from a builder. Can be either an Observable, a Promise or a vector. |
| 195 | + */ |
| 196 | +export type BuilderOutputLike = Observable<BuilderOutput> | Promise<BuilderOutput> | BuilderOutput; |
| 197 | + |
| 198 | + |
| 199 | +/** |
| 200 | + * A builder handler function. The function signature passed to `createBuilder()`. |
| 201 | + */ |
| 202 | +export interface BuilderHandlerFn<A extends json.JsonObject> { |
| 203 | + /** |
| 204 | + * Builders are defined by users to perform any kind of task, like building, testing or linting, |
| 205 | + * and should use this interface. |
| 206 | + * @param input The options (a JsonObject), validated by the schema and received by the |
| 207 | + * builder. This can include resolved options from the CLI or the workspace. |
| 208 | + * @param context A context that can be used to interact with the Architect framework. |
| 209 | + * @return One or many builder output. |
| 210 | + */ |
| 211 | + (input: A, context: BuilderContext): BuilderOutputLike; |
| 212 | +} |
| 213 | + |
| 214 | +/** |
| 215 | + * A Builder general information. This is generated by the host and is expanded by the host, but |
| 216 | + * the public API contains those fields. |
| 217 | + */ |
| 218 | +export type BuilderInfo = json.JsonObject & { |
| 219 | + builderName: string; |
| 220 | + description: string; |
| 221 | + optionSchema: json.schema.JsonSchema; |
| 222 | +}; |
| 223 | + |
| 224 | + |
| 225 | +/** |
| 226 | + * Returns a string of "project:target[:configuration]" for the target object. |
| 227 | + */ |
| 228 | +export function targetStringFromTarget({project, target, configuration}: Target) { |
| 229 | + return `${project}:${target}${configuration !== undefined ? ':' + configuration : ''}`; |
| 230 | +} |
0 commit comments