1 | import * as exp from "express";
|
2 | import { HandleCommand } from "./HandleCommand";
|
3 | import { HandleEvent } from "./HandleEvent";
|
4 | import { ExpressServerOptions } from "./internal/transport/express/ExpressServer";
|
5 | import { AutomationEventListener } from "./server/AutomationEventListener";
|
6 | import { AutomationMetadataProcessor } from "./spi/env/MetadataProcessor";
|
7 | import { SecretResolver } from "./spi/env/SecretResolver";
|
8 | import { GraphClientFactory } from "./spi/graph/GraphClientFactory";
|
9 | import { HttpClientFactory } from "./spi/http/httpClient";
|
10 | import { WebSocketFactory } from "./spi/http/wsClient";
|
11 | import { StatsDClientFactory } from "./spi/statsd/statsdClient";
|
12 | import { Maker } from "./util/constructionUtils";
|
13 | /**
|
14 | * Customize the express server configuration: For example to add custom routes
|
15 | *
|
16 | * Example:
|
17 | *
|
18 | * const newRouteCustomizer = (express: exp.Express, ...handlers: exp.RequestHandler[]) => {
|
19 | * express.get("/new-route", ...handlers, (req, res) => {
|
20 | * res.json({ key: "value" });
|
21 | * });
|
22 | * }
|
23 | */
|
24 | export declare type ExpressCustomizer = (express: exp.Express, ...handlers: exp.RequestHandler[]) => void;
|
25 | /**
|
26 | * Post process the configuration after is has been merged from the various locations, but
|
27 | * before starting the automation client.
|
28 | */
|
29 | export declare type ConfigurationPostProcessor<T = AnyOptions> = (configuration: Configuration) => Promise<Configuration & T>;
|
30 | /**
|
31 | * A computed banner
|
32 | */
|
33 | export interface Banner {
|
34 | /**
|
35 | * Banner content
|
36 | */
|
37 | banner: string;
|
38 | /**
|
39 | * Whether or not the banner content should be asciified
|
40 | */
|
41 | asciify: boolean;
|
42 | color: "black" | "red" | "green" | "yellow" | "blue" | "magenta" | "cyan" | "white" | "gray";
|
43 | }
|
44 | /**
|
45 | * A section that should be displayed in the banner.
|
46 | */
|
47 | export interface BannerSection {
|
48 | title: string;
|
49 | body: string;
|
50 | }
|
51 | /**
|
52 | * Custom configuration you can abuse to your benefit
|
53 | */
|
54 | export interface AnyOptions {
|
55 | /** Abuse goes here */
|
56 | [key: string]: any;
|
57 | }
|
58 | /**
|
59 | * Options for an automation node.
|
60 | */
|
61 | export interface AutomationOptions extends AnyOptions {
|
62 | /**
|
63 | * Automation name. If not given, the name is extracted from
|
64 | * the package.json.
|
65 | */
|
66 | name?: string;
|
67 | /**
|
68 | * Automation version. Must be a valid semantic version,
|
69 | * https://semver.org/. If not given, the version is extracted
|
70 | * from the package.json.
|
71 | */
|
72 | version?: string;
|
73 | /**
|
74 | * Atomist workspaces this automation will be registered with. Must be
|
75 | * specified if groups is not specified. Cannot be specified if
|
76 | * groups is specified.
|
77 | */
|
78 | workspaceIds?: string[];
|
79 | /**
|
80 | * DO NOT USE. Groups this automation will be registered with.
|
81 | * Must be specified if teams is not specified. Cannot be
|
82 | * specified if teams is specified. Providing groups indicates
|
83 | * this is a global automation, which can only successfully be
|
84 | * registered by Atomist.
|
85 | */
|
86 | groups?: string[];
|
87 | /**
|
88 | * If events should be queued when the registration is not
|
89 | * connected to the websocket, specificy "durable". "ephemeral"
|
90 | * is suited for testing and running locally and is the default.
|
91 | */
|
92 | policy?: "ephemeral" | "durable";
|
93 | /**
|
94 | * Atomist API Key used to authenticate the user starting the client.
|
95 | */
|
96 | apiKey?: string;
|
97 | /** HTTP configuration, useful for health checks */
|
98 | http?: {
|
99 | enabled?: boolean;
|
100 | client?: {
|
101 | factory?: HttpClientFactory;
|
102 | };
|
103 | } & Partial<ExpressServerOptions>;
|
104 | /** websocket configuration */
|
105 | ws?: {
|
106 | enabled?: boolean;
|
107 | client?: {
|
108 | factory?: WebSocketFactory;
|
109 | };
|
110 | termination?: {
|
111 | /**
|
112 | * If true, wait for up to `gracePeriod` milliseconds to
|
113 | * process in-flight and queued requests.
|
114 | */
|
115 | graceful?: boolean;
|
116 | /**
|
117 | * Grace period in milliseconds. Note the actual time to
|
118 | * shutdown gracefully may be more than twice this, as
|
119 | * this period is used to first wait for requests and then
|
120 | * used again to wait for any cluster workers to shutdown.
|
121 | * If some part of the shutdown hangs, it could take up to
|
122 | * ten times this period for all processes to exit.
|
123 | */
|
124 | gracePeriod?: number;
|
125 | };
|
126 | /** compress messages over websocket */
|
127 | compress?: boolean;
|
128 | /** timeout in milliseconds */
|
129 | timeout?: number;
|
130 | /** Configure backoff behavior on the WS connection */
|
131 | backoff?: {
|
132 | /**
|
133 | * Max number of the pending messages in the queue before
|
134 | * initiating backoff
|
135 | */
|
136 | threshold?: number;
|
137 | /** Interval in ms to check threshold */
|
138 | interval?: number;
|
139 | /**
|
140 | * Duration in ms the backend should backoff before sending
|
141 | * any more messages
|
142 | */
|
143 | duration?: number;
|
144 | /**
|
145 | * Factor (0 < x <= 1) multiply threshold to get to the lower backoff
|
146 | * boundary
|
147 | */
|
148 | factor?: number;
|
149 | };
|
150 | };
|
151 | graphql?: {
|
152 | client?: {
|
153 | factory: GraphClientFactory;
|
154 | };
|
155 | };
|
156 | /** Atomist API endpoints */
|
157 | endpoints?: {
|
158 | graphql?: string;
|
159 | api?: string;
|
160 | auth?: string;
|
161 | };
|
162 | /**
|
163 | * Post-processors can be used to modify the configuration after
|
164 | * all standard configuration loading has been done and before the
|
165 | * client is started. Post-processors return a configuration
|
166 | * promise so they can be asynchronous.
|
167 | */
|
168 | postProcessors?: ConfigurationPostProcessor[];
|
169 | }
|
170 | /**
|
171 | * Options useful when running an automation client in server mode.
|
172 | */
|
173 | export interface AutomationServerOptions extends AutomationOptions {
|
174 | /** environment automation is running in, e.g., "production" or "testing" */
|
175 | environment?: string;
|
176 | /**
|
177 | * Application identifier used for metrics send to statsd. If not
|
178 | * set, the automation client package name with any namespace
|
179 | * prefix removed is used.
|
180 | */
|
181 | application?: string;
|
182 | /** keywords useful for discovery */
|
183 | keywords?: string[];
|
184 | /** Whether and where to send application start and stop events to Atomist. */
|
185 | applicationEvents?: {
|
186 | enabled?: boolean;
|
187 | workspaceId?: string;
|
188 | };
|
189 | /**
|
190 | * Whether and how many workers to start up. If enabled is true
|
191 | * and workers is false, a number of workers equal to the number
|
192 | * of available CPUs will be started.
|
193 | */
|
194 | cluster?: {
|
195 | enabled?: boolean;
|
196 | workers?: number;
|
197 | maxConcurrentPerWorker?: number;
|
198 | };
|
199 | /** Logging configuration */
|
200 | logging?: {
|
201 | /** Log level, default is "info" */
|
202 | level?: "silly" | "debug" | "verbose" | "info" | "warn" | "error";
|
203 | /**
|
204 | * Custom log configuration, useful if your logging solution
|
205 | * requires host, port, token, etc. configuration.
|
206 | */
|
207 | custom?: any;
|
208 | /**
|
209 | * Print welcome banner; set to an arbitrary string to display,
|
210 | * default is name of automation-client
|
211 | */
|
212 | banner?: {
|
213 | enabled?: boolean;
|
214 | /** Message or Banner to be printed at the top of the banner */
|
215 | message?: string | ((configuration: Configuration) => Banner);
|
216 | /**
|
217 | * Add content to the banner which shows up between handlers and
|
218 | * footer
|
219 | */
|
220 | contributors?: Array<(configuration: Configuration) => string | BannerSection>;
|
221 | };
|
222 | /**
|
223 | * Log to file; set to file path to overwrite location and name of logfile,
|
224 | * defaults to ./log/automation-client.log in current working directory
|
225 | */
|
226 | file?: {
|
227 | enabled?: boolean;
|
228 | name?: string;
|
229 | level?: "silly" | "debug" | "verbose" | "info" | "warn" | "error";
|
230 | };
|
231 | };
|
232 | /** Redaction configuration */
|
233 | redact?: {
|
234 | /** Redact log messages */
|
235 | log?: boolean;
|
236 | /** Redact messages send via the message client */
|
237 | messages?: boolean;
|
238 | /** Register patterns to look for and optional replacements */
|
239 | patterns?: Array<{
|
240 | regexp: RegExp | string;
|
241 | replacement?: string;
|
242 | }>;
|
243 | };
|
244 | /** statsd config */
|
245 | statsd?: {
|
246 | /** Whether to send metrics statsd, default is false */
|
247 | enabled?: boolean;
|
248 | /**
|
249 | * statsd host. If not set, use the host-shots default,
|
250 | * "localhost" at the time of this writing.
|
251 | */
|
252 | host?: string;
|
253 | /**
|
254 | * statsd port. If not set, use the hot-shots default, 8125
|
255 | * at the time of this writing.
|
256 | */
|
257 | port?: number;
|
258 | /**
|
259 | * statsd client factory to create instances of StatsDClient
|
260 | */
|
261 | client?: {
|
262 | factory: StatsDClientFactory;
|
263 | };
|
264 | };
|
265 | /** Register a custom secret resolver */
|
266 | secretResolver?: SecretResolver;
|
267 | /** Register a custom AutomationMetadataProcessor */
|
268 | metadataProcessor?: AutomationMetadataProcessor;
|
269 | }
|
270 | /**
|
271 | * Atomist automation configuration.
|
272 | */
|
273 | export interface Configuration extends AutomationServerOptions {
|
274 | /**
|
275 | * Automation commands this package provides. If empty or null,
|
276 | * the package will be scanned for commands, which must be under a
|
277 | * directory named "commands".
|
278 | */
|
279 | commands?: Array<Maker<HandleCommand>>;
|
280 | /**
|
281 | * Automation event handlers this package provides. If empty or
|
282 | * null, the package will be scanned for event handlers, which
|
283 | * must be under a directory named "events".
|
284 | */
|
285 | events?: Array<Maker<HandleEvent>>;
|
286 | /** Custom event ingester */
|
287 | ingesters?: string[];
|
288 | /** Log and metric sinks */
|
289 | listeners?: AutomationEventListener[];
|
290 | }
|
291 | /**
|
292 | * User per-automation configuration
|
293 | */
|
294 | export interface ModuleOptions extends AutomationServerOptions {
|
295 | /** Automation name this configuration applies to. */
|
296 | name: string;
|
297 | /**
|
298 | * A valid version or version range, as defined by
|
299 | * https://www.npmjs.com/package/semver, this configuration
|
300 | * applies to. If not provided, it applies to all versions of the
|
301 | * named automation.
|
302 | */
|
303 | version?: string;
|
304 | }
|
305 | /**
|
306 | * User-wide configuration and user per-automation configuration
|
307 | */
|
308 | export interface UserConfig extends AutomationServerOptions {
|
309 | modules?: ModuleOptions[];
|
310 | }
|
311 | /**
|
312 | * Generate defaults for various configuration option values. These
|
313 | * will only be used if values are not provided by any source. Values
|
314 | * not provided here will be `undefined`.
|
315 | *
|
316 | * @return default configuration
|
317 | */
|
318 | export declare function defaultConfiguration(): Configuration;
|
319 | /**
|
320 | * Exposes the configuration for lookup of configuration values.
|
321 | * This is useful for components to obtain values eg. from configuration.custom
|
322 | * like user provided secrets etc.
|
323 | * @param {string} path the property path evaluated against the configuration instance
|
324 | * @returns {T}
|
325 | */
|
326 | export declare function configurationValue<T>(path?: string, defaultValue?: T): T;
|
327 | /**
|
328 | * Return user automation client configuration path.
|
329 | */
|
330 | export declare function userConfigPath(): string;
|
331 | /**
|
332 | * Return user automation client configuration paths including
|
333 | * such referenced by configuration profiles.
|
334 | */
|
335 | export declare function userConfigPaths(): string[];
|
336 | /**
|
337 | * Write user config securely, creating directories as necessary.
|
338 | */
|
339 | export declare function writeUserConfig(cfg: UserConfig): Promise<void>;
|
340 | /**
|
341 | * Read and return user config from UserConfigFile.
|
342 | */
|
343 | export declare function getUserConfig(): UserConfig;
|
344 | /**
|
345 | * Overwrite values in the former configuration with values in the
|
346 | * latter. The start object is modified.
|
347 | *
|
348 | * @param obj starting configuration
|
349 | * @param override configuration values to add/override those in start
|
350 | * @return resulting merged configuration
|
351 | */
|
352 | export declare function mergeConfigs(obj: Configuration, ...sources: Configuration[]): Configuration;
|
353 | /**
|
354 | * Overwrite values in the former configuration with values in the
|
355 | * latter. The start object is modified. Arrays are concatenated.
|
356 | *
|
357 | * @param obj starting configuration
|
358 | * @param override configuration values to add/override those in start
|
359 | * @return resulting merged configuration
|
360 | */
|
361 | export declare function deepMergeConfigs(obj: Configuration, ...sources: Configuration[]): Configuration;
|
362 | /**
|
363 | * Merge a user's global and proper per-module configuration, if it
|
364 | * exists. Values from the per-module configuration take precedence
|
365 | * over the user-wide values. Per-module configuration is gotten from
|
366 | * the first per-module configuration that matches name and,
|
367 | * optionally, the version is within the per-module configuration's
|
368 | * version range. A module configuration without a version range
|
369 | * matches the named module with any version. If no version is
|
370 | * provided, any version range is satisfied, meaning the first
|
371 | * per-module configuration with a matching name is used. If no name
|
372 | * is provide, only the user configuration is loaded. The first
|
373 | * per-module match is used. This means if you have multiple
|
374 | * configurations for the same named module and you want to include a
|
375 | * default configuration for that module, put a configuration without
|
376 | * a version range _after_ all the configurations with version ranges.
|
377 | * Note that only values from the first per-module match are used.
|
378 | *
|
379 | * @param userConfig the user's configuration, which may include per-module configuration
|
380 | * @param name automation client package name to load as module config if it exists
|
381 | * @param version automation client package version to load as module config if
|
382 | * version satifies module config version range
|
383 | * @return the merged module and user configuration
|
384 | */
|
385 | export declare function resolveModuleConfig(userConfig: UserConfig, name?: string, version?: string): AutomationServerOptions;
|
386 | /**
|
387 | * Try to read user config, overriding its values with a per-module
|
388 | * configuration that matches this automation.
|
389 | *
|
390 | * @param name automation client package name to load as module config if it exists
|
391 | * @param version automation client package version to load as module config if
|
392 | * version satifies module config version range
|
393 | * @return module-specific config with user config supplying defaults
|
394 | */
|
395 | export declare function loadUserConfiguration(name?: string, version?: string): AutomationServerOptions;
|
396 | /**
|
397 | * Load the automation configuration from the configuration object
|
398 | * exported from cfgPath and return it. If no configuration path is
|
399 | * provided, the package will be searched for a file named
|
400 | * atomist.config.js. If no atomist.config.js is found, an empty
|
401 | * object is returned. If more than one is found, an exception is
|
402 | * thrown.
|
403 | *
|
404 | * @param cfgPath location of automation configuration
|
405 | * @return automation configuration or undefined
|
406 | */
|
407 | export declare function loadAutomationConfig(configPath?: string): Promise<Configuration | undefined>;
|
408 | /**
|
409 | * Load the automation configuration from the configuration objects
|
410 | * exported and merged by all index.js files in the automation client.
|
411 | *
|
412 | * @return automation configuration
|
413 | */
|
414 | export declare function loadIndexConfig(): Promise<Configuration>;
|
415 | /**
|
416 | * Load configuration from the file defined by the ATOMIST_CONFIG_PATH
|
417 | * environment variable, if it the variable is defined and the file
|
418 | * exists, and return it. The contents of the ATOMIST_CONFIG_PATH
|
419 | * file should be serialized JSON of AutomationServerOptions. If the
|
420 | * environment variable is not defined or the file path specified by
|
421 | * its value cannot be read as JSON, an empty object is returned.
|
422 | *
|
423 | * @return automation server options
|
424 | */
|
425 | export declare function loadAtomistConfigPath(): AutomationServerOptions;
|
426 | /**
|
427 | * Load configuration from the ATOMIST_CONFIG environment variable, if
|
428 | * it the variable is defined, and merge it into the passed in
|
429 | * configuration. The value of the ATOMIST_CONFIG environment
|
430 | * variable should be serialized JSON of AutomationServerOptions. The
|
431 | * values from the environment variable will override values in the
|
432 | * passed in configuration. If the environment variable is not
|
433 | * defined, the passed in configuration is returned unchanged.
|
434 | *
|
435 | * @return automation server options
|
436 | */
|
437 | export declare function loadAtomistConfig(): AutomationServerOptions;
|
438 | /**
|
439 | * Examine environment, config, and cfg for Atomist workspace IDs.
|
440 | * The ATOMIST_WORKSPACES environment variable takes precedence over
|
441 | * the config "workspaceIds", which takes precedence over
|
442 | * cfg.workspaceId, which may be undefined, null, or an empty array.
|
443 | *
|
444 | * @param cfg current configuration, whose workspaceIds
|
445 | * properties may be modified by this function
|
446 | * @return the resolved workspace IDs
|
447 | */
|
448 | export declare function resolveWorkspaceIds(cfg: Configuration): string[];
|
449 | /**
|
450 | * Resolve the HTTP port from the environment and configuration. The
|
451 | * PORT environment variable takes precedence over the config value.
|
452 | */
|
453 | export declare function resolvePort(cfg: Configuration): number;
|
454 | /**
|
455 | * Resolve ATOMIST_ environment variables and add them to config.
|
456 | * Variables of like ATOMIST_custom_foo_bar will be converted to
|
457 | * a json path of custom.foo.bar.
|
458 | * @param {Configuration} cfg
|
459 | */
|
460 | export declare function resolveEnvironmentVariables(cfg: Configuration): void;
|
461 | /**
|
462 | * Resolve placeholders against the process.env.
|
463 | * Placeholders should be of form ${ENV_VAR}. Placeholders support default values
|
464 | * in case they aren't defined: ${ENV_VAR:default value}
|
465 | */
|
466 | export declare function resolvePlaceholders(cfg: Configuration, replacer?: (value: string) => Promise<string>, visited?: any[]): Promise<void>;
|
467 | /**
|
468 | * Invoke postProcessors on the provided configuration.
|
469 | */
|
470 | export declare function invokePostProcessors(cfg: Configuration): Promise<Configuration>;
|
471 | /**
|
472 | * Make sure final configuration has the minimum configuration it
|
473 | * needs. It will throw an error if required properties are missing.
|
474 | *
|
475 | * @param cfg final configuration
|
476 | */
|
477 | export declare function validateConfiguration(cfg: Configuration): void;
|
478 | /**
|
479 | * Load and populate the automation configuration. The configuration
|
480 | * is loaded from several locations with the following precedence from
|
481 | * highest to lowest.
|
482 | *
|
483 | * 1. `ATOMIST_` environment variables, see [[resolveEnvironmentVariables]]
|
484 | * 2. Configuration returned from the post-processors.
|
485 | * 3. Recognized environment variables, see [[resolveWorkspaceIds]],
|
486 | * [[resolvePort]]
|
487 | * 4. The value of the ATOMIST_CONFIG environment variable, parsed as
|
488 | * JSON and cast to AutomationServerOptions
|
489 | * 5. The contents of the ATOMIST_CONFIG_PATH file as AutomationServerOptions
|
490 | * 6. The contents of the user's client.config.json as UserConfig
|
491 | * resolving user and per-module configuration into Configuration
|
492 | * 7. The automation atomist.config.js or _all_ index.js files'
|
493 | * configurations exported as `configuration` from those files
|
494 | * 8. ProductionDefaultConfiguration if ATOMIST_ENV or NODE_ENV is set
|
495 | * to "production" or TestingDefaultConfiguration if ATOMIST_ENV or
|
496 | * NODE_ENV is set to "staging" or "testing", with ATOMIST_ENV
|
497 | * taking precedence over NODE_ENV.
|
498 | * 9. LocalDefaultConfiguration
|
499 | *
|
500 | * If any of the sources are missing, they are ignored. Any truthy
|
501 | * configuration values specified by sources of higher precedence
|
502 | * cause any values provided by sources of lower precedence to be
|
503 | * ignored. Arrays are replaced, not merged. Typically the only
|
504 | * required values in the configuration for a successful registration
|
505 | * are the apiKey and non-empty workspaceIds.
|
506 | *
|
507 | * Placeholder of the form `${ENV_VARIABLE}` in string configuration
|
508 | * values will get resolved against the environment. The resolution
|
509 | * happens after all of the above configuration sources have been
|
510 | * merged.
|
511 | *
|
512 | * After all sources are merged and the resulting configuration
|
513 | * processed for placeholders and environment variables, the
|
514 | * configuration is validated using [[validateConfiguration]].
|
515 | *
|
516 | * The configuration exported from the index.js (or atomist.config.js)
|
517 | * is modified to contain the final configuration values and returned
|
518 | * from this function.
|
519 | *
|
520 | * @param cfgPath path to file exporting the configuration object, if
|
521 | * not provided the package is searched for one
|
522 | * @return merged configuration object
|
523 | */
|
524 | export declare function loadConfiguration(cfgPath?: string): Promise<Configuration>;
|
525 | /**
|
526 | * Default set of regular expressions used to remove sensitive
|
527 | * information from messages and logs. The entries are applied in
|
528 | * order, so more specific regular expressions should be placed
|
529 | * earlier in the list to avoid a shorter replacement preventing a
|
530 | * longer replacement from being applied.
|
531 | */
|
532 | export declare const DEFAULT_REDACTION_PATTERNS: {
|
533 | regexp: RegExp;
|
534 | replacement: string;
|
535 | }[];
|
536 | /**
|
537 | * Default configuration when running in neither testing or
|
538 | * production.
|
539 | */
|
540 | export declare const LocalDefaultConfiguration: Configuration;
|
541 | /**
|
542 | * Configuration defaults for production environments.
|
543 | */
|
544 | export declare const ProductionDefaultConfiguration: Partial<Configuration>;
|
545 | /**
|
546 | * Configuration defaults for pre-production environments.
|
547 | */
|
548 | export declare const TestingDefaultConfiguration: Partial<Configuration>;
|
549 | //# sourceMappingURL=configuration.d.ts.map |
\ | No newline at end of file |