UNPKG

26.4 kBJavaScriptView Raw
1"use strict";
2/*
3 * Copyright © 2018 Atomist, Inc.
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <https://www.gnu.org/licenses/>.
17 */
18Object.defineProperty(exports, "__esModule", { value: true });
19const appRoot = require("app-root-path");
20const cluster = require("cluster");
21const fs = require("fs-extra");
22const glob = require("glob");
23const stringify = require("json-stringify-safe");
24const _ = require("lodash");
25const os = require("os");
26const p = require("path");
27const semver = require("semver");
28const globals_1 = require("./globals");
29const config_1 = require("./internal/util/config");
30const string_1 = require("./internal/util/string");
31const axiosHttpClient_1 = require("./spi/http/axiosHttpClient");
32const logger_1 = require("./util/logger");
33const packageJson_1 = require("./util/packageJson");
34/**
35 * Generate defaults for various configuration option values. These
36 * will only be used if values are not provided by any source. Values
37 * not provided here will be `undefined`.
38 *
39 * @return default configuration
40 */
41function defaultConfiguration() {
42 const pj = packageJson_1.loadHostPackageJson() || {};
43 pj.name = pj.name || "atm-client-" + string_1.guid();
44 pj.version = pj.version || "0.0.0";
45 pj.keywords = pj.keywords || [];
46 const cfg = loadDefaultConfiguration();
47 cfg.name = pj.name;
48 cfg.version = pj.version;
49 cfg.keywords = pj.keywords;
50 cfg.application = pj.name.replace(/^@.*?\//, "");
51 return cfg;
52}
53exports.defaultConfiguration = defaultConfiguration;
54/**
55 * Exposes the configuration for lookup of configuration values.
56 * This is useful for components to obtain values eg. from configuration.custom
57 * like user provided secrets etc.
58 * @param {string} path the property path evaluated against the configuration instance
59 * @returns {T}
60 */
61function configurationValue(path, defaultValue) {
62 if (globals_1.automationClientInstance()) {
63 const conf = globals_1.automationClientInstance().configuration;
64 let value;
65 if (!path || path.length === 0) {
66 value = conf;
67 }
68 else {
69 value = _.get(conf, path);
70 }
71 if (value != null) {
72 return value;
73 }
74 else if (defaultValue !== undefined) {
75 return defaultValue;
76 }
77 }
78 else if (defaultValue) {
79 return defaultValue;
80 }
81 throw new Error(`Required @Value '${path}' not available`);
82}
83exports.configurationValue = configurationValue;
84/**
85 * Return the default configuration based on NODE_ENV or ATOMIST_ENV.
86 * ATOMIST_ENV takes precedence if it is set.
87 */
88function loadDefaultConfiguration() {
89 const cfg = exports.LocalDefaultConfiguration;
90 let envSpecificCfg = {};
91 const nodeEnv = process.env.ATOMIST_ENV || process.env.NODE_ENV;
92 if (nodeEnv === "production") {
93 envSpecificCfg = exports.ProductionDefaultConfiguration;
94 }
95 else if (nodeEnv === "staging" || nodeEnv === "testing") {
96 envSpecificCfg = exports.TestingDefaultConfiguration;
97 }
98 else if (nodeEnv) {
99 cfg.environment = nodeEnv;
100 }
101 return mergeConfigs(cfg, envSpecificCfg);
102}
103/**
104 * Return Atomist user configuration directory.
105 */
106function userConfigDir() {
107 return p.join(os.homedir(), ".atomist");
108}
109/**
110 * Return user automation client configuration path.
111 */
112function userConfigPath() {
113 const clientConfigFile = "client.config.json";
114 return p.join(userConfigDir(), clientConfigFile);
115}
116exports.userConfigPath = userConfigPath;
117/**
118 * Write user config securely, creating directories as necessary.
119 */
120function writeUserConfig(cfg) {
121 const cfgDir = userConfigDir();
122 return fs.ensureDir(cfgDir)
123 .then(() => fs.chmod(cfgDir, 0o700))
124 .then(() => fs.writeJson(userConfigPath(), cfg, {
125 spaces: 2,
126 encoding: "utf8",
127 mode: 0o600,
128 }));
129}
130exports.writeUserConfig = writeUserConfig;
131/**
132 * Read and return user config from UserConfigFile.
133 */
134function getUserConfig() {
135 if (fs.existsSync(userConfigPath())) {
136 try {
137 const cfg = fs.readJsonSync(userConfigPath());
138 // user config should not have name or version
139 if (cfg.name) {
140 delete cfg.name;
141 }
142 if (cfg.version) {
143 delete cfg.version;
144 }
145 return cfg;
146 }
147 catch (e) {
148 e.message = `Failed to read user config: ${e.message}`;
149 throw e;
150 }
151 }
152 return undefined;
153}
154exports.getUserConfig = getUserConfig;
155/**
156 * Log the loading of a configuration
157 *
158 * @param source name of configuration source
159 */
160function cfgLog(source) {
161 if (cluster.isMaster) {
162 logger_1.logger.debug(`Loading ${source} configuration`);
163 }
164}
165/**
166 * Overwrite values in the former configuration with values in the
167 * latter. The start object is modified.
168 *
169 * @param obj starting configuration
170 * @param override configuration values to add/override those in start
171 * @return resulting merged configuration
172 */
173function mergeConfigs(obj, ...sources) {
174 return _.mergeWith(obj, ...sources, (objValue, srcValue) => {
175 if (_.isArray(srcValue)) {
176 return srcValue;
177 }
178 });
179}
180exports.mergeConfigs = mergeConfigs;
181/**
182 * Overwrite values in the former configuration with values in the
183 * latter. The start object is modified. Arrays are concatenated.
184 *
185 * @param obj starting configuration
186 * @param override configuration values to add/override those in start
187 * @return resulting merged configuration
188 */
189function deepMergeConfigs(obj, ...sources) {
190 return _.mergeWith(obj, ...sources, (objValue, srcValue) => {
191 if (_.isArray(objValue) && srcValue) {
192 return objValue.concat(srcValue);
193 }
194 });
195}
196exports.deepMergeConfigs = deepMergeConfigs;
197/**
198 * Merge a user's global and proper per-module configuration, if it
199 * exists. Values from the per-module configuration take precedence
200 * over the user-wide values. Per-module configuration is gotten from
201 * the first per-module configuration that matches name and,
202 * optionally, the version is within the per-module configuration's
203 * version range. A module configuration without a version range
204 * matches the named module with any version. If no version is
205 * provided, any version range is satisfied, meaning the first
206 * per-module configuration with a matching name is used. If no name
207 * is provide, only the user configuration is loaded. The first
208 * per-module match is used. This means if you have multiple
209 * configurations for the same named module and you want to include a
210 * default configuration for that module, put a configuration without
211 * a version range _after_ all the configurations with version ranges.
212 * Note that only values from the first per-module match are used.
213 *
214 * @param userConfig the user's configuration, which may include per-module configuration
215 * @param name automation client package name to load as module config if it exists
216 * @param version automation client package version to load as module config if
217 * version satifies module config version range
218 * @return the merged module and user configuration
219 */
220function resolveModuleConfig(userConfig, name, version) {
221 const cfg = {};
222 if (userConfig) {
223 cfgLog("user");
224 const uc = _.cloneDeep(userConfig);
225 let mc = {};
226 if (userConfig.modules) {
227 delete uc.modules;
228 if (name) {
229 let modCfg;
230 const moduleConfigs = userConfig.modules.filter(m => m.name === name);
231 if (version) {
232 modCfg = moduleConfigs.find(m => !m.version || semver.satisfies(version, m.version));
233 }
234 else if (moduleConfigs.length > 0) {
235 modCfg = moduleConfigs[0];
236 }
237 if (modCfg) {
238 cfgLog("module");
239 if (modCfg.name) {
240 delete modCfg.name;
241 }
242 if (modCfg.version) {
243 delete modCfg.version;
244 }
245 mc = modCfg;
246 }
247 }
248 }
249 mergeConfigs(cfg, uc, mc);
250 }
251 return cfg;
252}
253exports.resolveModuleConfig = resolveModuleConfig;
254/**
255 * Try to read user config, overriding its values with a per-module
256 * configuration that matches this automation.
257 *
258 * @param name automation client package name to load as module config if it exists
259 * @param version automation client package version to load as module config if
260 * version satifies module config version range
261 * @return module-specific config with user config supplying defaults
262 */
263function loadUserConfiguration(name, version) {
264 const userConfig = getUserConfig();
265 return resolveModuleConfig(userConfig, name, version);
266}
267exports.loadUserConfiguration = loadUserConfiguration;
268/**
269 * Load the automation configuration from the configuration object
270 * exported from cfgPath and return it. If no configuration path is
271 * provided, the package will be searched for a file named
272 * atomist.config.js. If no atomist.config.js is found, an empty
273 * object is returned. If more than one is found, an exception is
274 * thrown.
275 *
276 * @param cfgPath location of automation configuration
277 * @return automation configuration or undefined
278 */
279function loadAutomationConfig(cfgPath) {
280 if (!cfgPath) {
281 const cfgFile = "atomist.config.js";
282 const files = glob.sync(`${appRoot.path}/**/${cfgFile}`, { ignore: ["**/{.git,node_modules}/**"] });
283 if (files.length === 1) {
284 cfgPath = files[0];
285 }
286 else if (files.length > 1) {
287 throw new Error(`More than one automation configuration found in package: ${files.join(", ")}`);
288 }
289 }
290 if (cfgPath) {
291 try {
292 const cfg = require(cfgPath).configuration;
293 cfgLog("automation config");
294 return cfg;
295 }
296 catch (e) {
297 e.message = `Failed to load ${cfgPath}.configuration: ${e.message}`;
298 throw e;
299 }
300 }
301 return undefined;
302}
303exports.loadAutomationConfig = loadAutomationConfig;
304/**
305 * Load the automation configuration from the configuration objects
306 * exported and merged by all index.js files in the automation client.
307 *
308 * @return automation configuration
309 */
310function loadIndexConfig() {
311 const cfgFile = "index.js";
312 const files = glob.sync(`${appRoot.path}/**/${cfgFile}`, { ignore: ["**/{.git,node_modules}/**"] });
313 if (files.length > 0) {
314 const cfgs = files.map(f => {
315 try {
316 const cfg = require(f).configuration || {};
317 cfgLog("index config");
318 return cfg;
319 }
320 catch (e) {
321 logger_1.logger.debug(`Failed to load ${f}.configuration: ${e.message}`);
322 return {};
323 }
324 });
325 return deepMergeConfigs({}, ...cfgs);
326 }
327 return {};
328}
329exports.loadIndexConfig = loadIndexConfig;
330/**
331 * Load configuration from the file defined by the ATOMIST_CONFIG_PATH
332 * environment variable, if it the variable is defined and the file
333 * exists, and return it. The contents of the ATOMIST_CONFIG_PATH
334 * file should be serialized JSON of AutomationServerOptions. If the
335 * environment variable is not defined or the file path specified by
336 * its value cannot be read as JSON, an empty object is returned.
337 *
338 * @return automation server options
339 */
340function loadAtomistConfigPath() {
341 let cfg = {};
342 if (process.env.ATOMIST_CONFIG_PATH) {
343 try {
344 cfg = fs.readJsonSync(process.env.ATOMIST_CONFIG_PATH);
345 cfgLog("ATOMIST_CONFIG_PATH");
346 }
347 catch (e) {
348 e.message = `Failed to read ATOMIST_CONFIG_PATH: ${e.message}`;
349 throw e;
350 }
351 }
352 return cfg;
353}
354exports.loadAtomistConfigPath = loadAtomistConfigPath;
355/**
356 * Load configuration from the ATOMIST_CONFIG environment variable, if
357 * it the variable is defined, and merge it into the passed in
358 * configuration. The value of the ATOMIST_CONFIG environment
359 * variable should be serialized JSON of AutomationServerOptions. The
360 * values from the environment variable will override values in the
361 * passed in configuration. If the environment variable is not
362 * defined, the passed in configuration is returned unchanged.
363 *
364 * @return automation server options
365 */
366function loadAtomistConfig() {
367 let cfg = {};
368 if (process.env.ATOMIST_CONFIG) {
369 try {
370 cfg = JSON.parse(process.env.ATOMIST_CONFIG);
371 cfgLog("ATOMIST_CONFIG");
372 }
373 catch (e) {
374 e.message = `Failed to parse contents of ATOMIST_CONFIG environment variable: ${e.message}`;
375 throw e;
376 }
377 }
378 return cfg;
379}
380exports.loadAtomistConfig = loadAtomistConfig;
381/**
382 * Examine environment, config, and cfg for Atomist workspace IDs.
383 * The ATOMIST_WORKSPACES environment variable takes precedence over
384 * the configuration "workspaceIds", which takes precedence over
385 * cfg.workspaceId, which may be undefined, null, or an empty array.
386 * If the ATOMIST_WORKSPACES environment variable is not set,
387 * workspaceIds is not set in config, and workspaceIds is falsey in
388 * cfg and teamIds is resolvable from the configuration, workspaceIds
389 * is set to teamIds.
390 *
391 * @param cfg current configuration, whose workspaceIds and teamIds
392 * properties may be modified by this function
393 * @return the resolved workspace IDs
394 */
395function resolveWorkspaceIds(cfg) {
396 if (process.env.ATOMIST_WORKSPACES) {
397 cfg.workspaceIds = process.env.ATOMIST_WORKSPACES.split(",");
398 }
399 else if (config_1.config("workspaceIds")) {
400 cfg.workspaceIds = config_1.config("workspaceIds");
401 }
402 return cfg.workspaceIds;
403}
404exports.resolveWorkspaceIds = resolveWorkspaceIds;
405/**
406 * Resolve a value from a environment variables or configuration keys.
407 * The environment variables are checked in order and take precedence
408 * over the configuration key, which are also checked in order. If
409 * no truthy values are found, undefined is returned.
410 *
411 * @param environmentVariables environment variables to check
412 * @param configKeyPaths configuration keys, as JSON paths, to check
413 * @param defaultValue value to use if no environment variables or config keys have values
414 * @return first truthy value found, or defaultValue
415 */
416function resolveConfigurationValue(environmentVariables, configKeyPaths, defaultValue) {
417 for (const ev of environmentVariables) {
418 if (process.env[ev]) {
419 return process.env[ev];
420 }
421 }
422 for (const cv of configKeyPaths) {
423 if (config_1.config(cv)) {
424 return config_1.config(cv);
425 }
426 }
427 return defaultValue;
428}
429exports.resolveConfigurationValue = resolveConfigurationValue;
430/**
431 * Resolve the HTTP port from the environment and configuration. The
432 * PORT environment variable takes precedence over the config value.
433 */
434function resolvePort(cfg) {
435 if (process.env.PORT) {
436 cfg.http.port = parseInt(process.env.PORT, 10);
437 }
438 return cfg.http.port;
439}
440exports.resolvePort = resolvePort;
441const EnvironmentVariablePrefix = "ATOMIST_";
442/**
443 * Resolve ATOMIST_ environment variables and add them to config.
444 * Variables of like ATOMIST_custom_foo_bar will be converted to
445 * a json path of custom.foo.bar.
446 * @param {Configuration} cfg
447 */
448function resolveEnvironmentVariables(cfg) {
449 for (const key in process.env) {
450 if (key.startsWith(EnvironmentVariablePrefix)
451 && process.env.hasOwnProperty(key)) {
452 const cleanKey = key.slice(EnvironmentVariablePrefix.length).split("_").join(".");
453 if (cleanKey[0] !== cleanKey[0].toUpperCase()) {
454 _.update(cfg, cleanKey, () => process.env[key]);
455 }
456 }
457 }
458}
459exports.resolveEnvironmentVariables = resolveEnvironmentVariables;
460/**
461 * Resolve placeholders against the process.env.
462 * Placeholders should be of form ${ENV_VAR}. Placeholders support default values
463 * in case they aren't defined: ${ENV_VAR:default value}
464 * @param {Configuration} config
465 */
466function resolvePlaceholders(cfg) {
467 resolvePlaceholdersRecursively(cfg, []);
468}
469exports.resolvePlaceholders = resolvePlaceholders;
470function resolvePlaceholdersRecursively(obj, visited) {
471 if (!visited.includes(obj)) {
472 visited.push(obj);
473 for (const property in obj) {
474 if (obj.hasOwnProperty(property)) {
475 if (typeof obj[property] === "object") {
476 resolvePlaceholdersRecursively(obj[property], visited);
477 }
478 else if (typeof obj[property] === "string") {
479 obj[property] = resolvePlaceholder(obj[property]);
480 }
481 }
482 }
483 }
484}
485const PlaceholderExpression = /\$\{([.a-zA-Z_-]+)([.:0-9a-zA-Z-_ \" ]+)*\}/g;
486function resolvePlaceholder(value) {
487 if (PlaceholderExpression.test(value)) {
488 PlaceholderExpression.lastIndex = 0;
489 let result;
490 // tslint:disable-next-line:no-conditional-assignment
491 while (result = PlaceholderExpression.exec(value)) {
492 const fm = result[0];
493 const envValue = process.env[result[1]];
494 const defaultValue = result[2] ? result[2].trim().slice(1) : undefined;
495 if (envValue) {
496 value = value.split(fm).join(envValue);
497 }
498 else if (defaultValue) {
499 value = value.split(fm).join(defaultValue);
500 }
501 else {
502 throw new Error(`Environment variable '${result[1]}' is not defined`);
503 }
504 }
505 }
506 return value;
507}
508/**
509 * Invoke postProcessors on the provided configuration.
510 */
511function invokePostProcessors(cfg) {
512 return cfg.postProcessors.reduce((pp, fp) => pp.then(fp), Promise.resolve(cfg));
513}
514exports.invokePostProcessors = invokePostProcessors;
515/**
516 * Make sure final configuration has the minimum configuration it
517 * needs. It will throw an error if required properties are missing.
518 *
519 * @param cfg final configuration
520 */
521function validateConfiguration(cfg) {
522 if (!cfg) {
523 throw new Error(`no configuration defined`);
524 }
525 const errors = [];
526 if (!cfg.name) {
527 errors.push("you must set a 'name' property in your configuration");
528 }
529 if (!cfg.version) {
530 errors.push("you must set a 'version' property in your configuration");
531 }
532 if (!cfg.apiKey) {
533 logger_1.logger.info("To obtain an 'apiKey' visit https://app.atomist.com/apikeys and run 'atomist config' " +
534 "to configure the apiKey in your local configuration");
535 errors.push("you must set an 'apiKey' property in your configuration");
536 }
537 cfg.workspaceIds = cfg.workspaceIds || [];
538 cfg.groups = cfg.groups || [];
539 if (cfg.workspaceIds.length < 1 && cfg.groups.length < 1) {
540 errors.push("you must either provide an array of 'groups' in your configuration or, more likely, provide " +
541 "an array of 'workspaceIds' in your configuration or set the ATOMIST_WORKSPACES environment variable " +
542 "to a comma-separated list of workspace IDs");
543 }
544 if (cfg.workspaceIds.length > 0 && cfg.groups.length > 0) {
545 errors.push("you cannot specify both 'workspaceIds' and 'groups' in your configuration, you must set one " +
546 "to an empty array");
547 }
548 if (errors.length > 0) {
549 const msg = `Configuration (${stringify(cfg, string_1.obfuscateJson)}) is not correct: ${errors.join("; ")}`;
550 throw new Error(msg);
551 }
552}
553exports.validateConfiguration = validateConfiguration;
554/**
555 * Load and populate the automation configuration. The configuration
556 * is loaded from several locations with the following precedence from
557 * highest to lowest.
558 *
559 * 0. Recognized environment variables (see below)
560 * 1. The value of the ATOMIST_CONFIG environment variable, parsed as
561 * JSON and cast to AutomationServerOptions
562 * 2. The contents of the ATOMIST_CONFIG_PATH file as AutomationServerOptions
563 * 3. The contents of the user's client.config.json as UserConfig
564 * resolving user and per-module configuration into Configuration
565 * 4. The automation's index.js (or atomist.config.js) exported configuration as
566 * Configuration
567 * 5. ProductionDefaultConfiguration if ATOMIST_ENV or NODE_ENV is set
568 * to "production" or TestingDefaultConfiguration if ATOMIST_ENV or
569 * NODE_ENV is set to "staging" or "testing", with ATOMIST_ENV
570 * taking precedence over NODE_ENV.
571 * 6. LocalDefaultConfiguration
572 *
573 * If any of the sources are missing, they are ignored. Any truthy
574 * configuration values specified by sources of higher precedence
575 * cause any values provided by sources of lower precedence to be
576 * ignored. Arrays are replaced, not merged. Typically the only
577 * required values in the configuration for a successful registration
578 * are the apiKey and non-empty workspaceIds.
579 *
580 * Placeholder of the form `${ENV_VARIABLE}` in string configuration
581 * values will get resolved against the environment. The resolution
582 * happens at the very end when all configs have been merged.
583 *
584 * The configuration exported from the index.js (or atomist.config.js) is modified
585 * to contain the final configuration values and returned from this
586 * function.
587 *
588 * @param cfgPath path to file exporting the configuration object, if
589 * not provided the package is searched for one
590 * @return merged configuration object
591 */
592function loadConfiguration(cfgPath) {
593 // Register the logger globally so that downstream modules can see it
594 global.__logger = logger_1.logger;
595 let cfg;
596 try {
597 const defCfg = defaultConfiguration();
598 const autoCfg = loadAutomationConfig(cfgPath) || loadIndexConfig();
599 const userCfg = loadUserConfiguration(defCfg.name, defCfg.version);
600 const atmPathCfg = loadAtomistConfigPath();
601 const atmCfg = loadAtomistConfig();
602 cfg = mergeConfigs({}, defCfg, autoCfg, userCfg, atmPathCfg, atmCfg);
603 resolveWorkspaceIds(cfg);
604 resolvePort(cfg);
605 resolveEnvironmentVariables(cfg);
606 resolvePlaceholders(cfg);
607 }
608 catch (e) {
609 logger_1.logger.error(`Failed to load configuration: ${e.message}`);
610 if (e.stack) {
611 logger_1.logger.error(`Stack trace:\n${e.stack}`);
612 }
613 return Promise.reject(e);
614 }
615 return invokePostProcessors(cfg)
616 .then(completeCfg => {
617 completeCfg.postProcessors = [];
618 try {
619 resolvePlaceholders(completeCfg);
620 validateConfiguration(completeCfg);
621 }
622 catch (e) {
623 return Promise.reject(e);
624 }
625 return Promise.resolve(completeCfg);
626 });
627}
628exports.loadConfiguration = loadConfiguration;
629/**
630 * Default configuration when running in neither testing or
631 * production.
632 */
633exports.LocalDefaultConfiguration = {
634 workspaceIds: [],
635 groups: [],
636 environment: "local",
637 policy: "ephemeral",
638 endpoints: {
639 api: "https://automation.atomist.com/registration",
640 graphql: "https://automation.atomist.com/graphql/team",
641 },
642 http: {
643 enabled: true,
644 host: "127.0.0.1",
645 auth: {
646 basic: {
647 enabled: false,
648 },
649 bearer: {
650 enabled: false,
651 },
652 },
653 customizers: [],
654 client: {
655 factory: axiosHttpClient_1.DefaultHttpClientFactory,
656 },
657 },
658 ws: {
659 enabled: true,
660 termination: {
661 graceful: false,
662 gracePeriod: 10000,
663 },
664 compress: false,
665 timeout: 10000,
666 },
667 applicationEvents: {
668 enabled: false,
669 },
670 cluster: {
671 enabled: false,
672 },
673 logging: {
674 level: "debug",
675 file: {
676 enabled: true,
677 level: "debug",
678 },
679 banner: {
680 enabled: true,
681 contributors: [],
682 },
683 },
684 statsd: {
685 enabled: false,
686 },
687 commands: null,
688 events: null,
689 ingesters: [],
690 listeners: [],
691 postProcessors: [],
692};
693/**
694 * Configuration defaults for production environments.
695 */
696exports.ProductionDefaultConfiguration = {
697 environment: "production",
698 policy: "durable",
699 http: {
700 port: 2866,
701 auth: {
702 basic: {
703 enabled: true,
704 },
705 bearer: {
706 enabled: true,
707 },
708 },
709 },
710 ws: {
711 termination: {
712 graceful: true,
713 },
714 compress: true,
715 },
716 applicationEvents: {
717 enabled: true,
718 },
719 cluster: {
720 enabled: true,
721 },
722 logging: {
723 level: "info",
724 file: {
725 enabled: false,
726 },
727 },
728 statsd: {
729 enabled: true,
730 },
731};
732/**
733 * Configuration defaults for pre-production environments.
734 */
735exports.TestingDefaultConfiguration = {
736 environment: "testing",
737 policy: "durable",
738 http: {
739 auth: {
740 basic: {
741 enabled: true,
742 },
743 bearer: {
744 enabled: true,
745 },
746 },
747 },
748 ws: {
749 termination: {
750 graceful: true,
751 },
752 compress: true,
753 },
754 applicationEvents: {
755 enabled: true,
756 },
757 cluster: {
758 enabled: true,
759 },
760 logging: {
761 level: "info",
762 file: {
763 enabled: false,
764 },
765 },
766 statsd: {
767 enabled: true,
768 },
769};
770//# sourceMappingURL=configuration.js.map
\No newline at end of file