dotcom-tool-kit 2.2.3 → 2.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/config.d.ts CHANGED
@@ -1,16 +1,16 @@
1
1
  import type { Logger } from 'winston';
2
2
  import type { HookTask } from './hook';
3
3
  import { Conflict } from './conflict';
4
- import { TaskClass, Hook, Plugin } from '@dotcom-tool-kit/types';
4
+ import { TaskClass, Hook, Plugin, Validated } from '@dotcom-tool-kit/types';
5
5
  export interface PluginOptions {
6
6
  options: Record<string, unknown>;
7
7
  plugin: Plugin;
8
8
  forPlugin: Plugin;
9
9
  }
10
- export interface Config {
10
+ export interface RawConfig {
11
11
  root: string;
12
12
  plugins: {
13
- [id: string]: Plugin;
13
+ [id: string]: Validated<Plugin>;
14
14
  };
15
15
  resolvedPlugins: Set<Plugin>;
16
16
  tasks: {
@@ -26,7 +26,12 @@ export interface Config {
26
26
  [id: string]: Hook | Conflict<Hook>;
27
27
  };
28
28
  }
29
- export interface ValidConfig extends Config {
29
+ export declare type ValidPluginsConfig = Omit<RawConfig, 'plugins'> & {
30
+ plugins: {
31
+ [id: string]: Plugin;
32
+ };
33
+ };
34
+ export interface ValidConfig extends ValidPluginsConfig {
30
35
  tasks: {
31
36
  [id: string]: TaskClass;
32
37
  };
@@ -40,13 +45,14 @@ export interface ValidConfig extends Config {
40
45
  [id: string]: Hook;
41
46
  };
42
47
  }
43
- export declare const createConfig: () => Config;
44
- export declare function validateConfig(config: Config): asserts config is ValidConfig;
48
+ export declare const createConfig: () => RawConfig;
49
+ export declare function validateConfig(config: ValidPluginsConfig): asserts config is ValidConfig;
50
+ export declare function validatePlugins(config: RawConfig): Validated<ValidPluginsConfig>;
45
51
  export declare function checkInstall(config: ValidConfig): Promise<void>;
46
52
  export declare function loadConfig(logger: Logger, options?: {
47
53
  validate?: true;
48
54
  }): Promise<ValidConfig>;
49
55
  export declare function loadConfig(logger: Logger, options?: {
50
56
  validate?: false;
51
- }): Promise<Config>;
57
+ }): Promise<RawConfig>;
52
58
  //# sourceMappingURL=config.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AAErC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAA;AAEtC,OAAO,EAAE,QAAQ,EAA+C,MAAM,YAAY,CAAA;AAElF,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAA;AAYhE,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAChC,MAAM,EAAE,MAAM,CAAA;IACd,SAAS,EAAE,MAAM,CAAA;CAClB;AAED,MAAM,WAAW,MAAM;IACrB,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE;QAAE,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAA;IACjC,eAAe,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;IAC5B,KAAK,EAAE;QAAE,CAAC,EAAE,EAAE,MAAM,GAAG,SAAS,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAA;KAAE,CAAA;IACxD,SAAS,EAAE;QAAE,CAAC,EAAE,EAAE,MAAM,GAAG,QAAQ,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAA;KAAE,CAAA;IAC1D,OAAO,EAAE;QAAE,CAAC,EAAE,EAAE,MAAM,GAAG,aAAa,GAAG,QAAQ,CAAC,aAAa,CAAC,GAAG,SAAS,CAAA;KAAE,CAAA;IAC9E,KAAK,EAAE;QAAE,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAA;KAAE,CAAA;CAC/C;AAED,MAAM,WAAW,WAAY,SAAQ,MAAM;IACzC,KAAK,EAAE;QAAE,CAAC,EAAE,EAAE,MAAM,GAAG,SAAS,CAAA;KAAE,CAAA;IAClC,SAAS,EAAE;QAAE,CAAC,EAAE,EAAE,MAAM,GAAG,QAAQ,CAAA;KAAE,CAAA;IACrC,OAAO,EAAE;QAAE,CAAC,EAAE,EAAE,MAAM,GAAG,aAAa,CAAA;KAAE,CAAA;IACxC,KAAK,EAAE;QAAE,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAA;CAC9B;AAID,eAAO,MAAM,YAAY,QAAO,MAQ9B,CAAA;AAQF,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,WAAW,CAuF5E;AAED,wBAAsB,YAAY,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAWrE;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;IAAE,QAAQ,CAAC,EAAE,IAAI,CAAA;CAAE,GAAG,OAAO,CAAC,WAAW,CAAC,CAAA;AAC/F,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;IAAE,QAAQ,CAAC,EAAE,KAAK,CAAA;CAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AAErC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAA;AAEtC,OAAO,EAAE,QAAQ,EAA+C,MAAM,YAAY,CAAA;AAElF,OAAO,EAAE,SAAS,EAAE,IAAI,EAAgB,MAAM,EAAmB,SAAS,EAAE,MAAM,wBAAwB,CAAA;AAY1G,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAChC,MAAM,EAAE,MAAM,CAAA;IACd,SAAS,EAAE,MAAM,CAAA;CAClB;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE;QAAE,CAAC,EAAE,EAAE,MAAM,GAAG,SAAS,CAAC,MAAM,CAAC,CAAA;KAAE,CAAA;IAC5C,eAAe,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;IAC5B,KAAK,EAAE;QAAE,CAAC,EAAE,EAAE,MAAM,GAAG,SAAS,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAA;KAAE,CAAA;IACxD,SAAS,EAAE;QAAE,CAAC,EAAE,EAAE,MAAM,GAAG,QAAQ,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAA;KAAE,CAAA;IAC1D,OAAO,EAAE;QAAE,CAAC,EAAE,EAAE,MAAM,GAAG,aAAa,GAAG,QAAQ,CAAC,aAAa,CAAC,GAAG,SAAS,CAAA;KAAE,CAAA;IAC9E,KAAK,EAAE;QAAE,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAA;KAAE,CAAA;CAC/C;AAED,oBAAY,kBAAkB,GAAG,IAAI,CAAC,SAAS,EAAE,SAAS,CAAC,GAAG;IAC5D,OAAO,EAAE;QAAE,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAA;CAClC,CAAA;AAED,MAAM,WAAW,WAAY,SAAQ,kBAAkB;IACrD,KAAK,EAAE;QAAE,CAAC,EAAE,EAAE,MAAM,GAAG,SAAS,CAAA;KAAE,CAAA;IAClC,SAAS,EAAE;QAAE,CAAC,EAAE,EAAE,MAAM,GAAG,QAAQ,CAAA;KAAE,CAAA;IACrC,OAAO,EAAE;QAAE,CAAC,EAAE,EAAE,MAAM,GAAG,aAAa,CAAA;KAAE,CAAA;IACxC,KAAK,EAAE;QAAE,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAA;CAC9B;AAID,eAAO,MAAM,YAAY,QAAO,SAQ9B,CAAA;AAQF,wBAAgB,cAAc,CAAC,MAAM,EAAE,kBAAkB,GAAG,OAAO,CAAC,MAAM,IAAI,WAAW,CAuFxF;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,SAAS,GAAG,SAAS,CAAC,kBAAkB,CAAC,CAKhF;AAED,wBAAsB,YAAY,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAWrE;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;IAAE,QAAQ,CAAC,EAAE,IAAI,CAAA;CAAE,GAAG,OAAO,CAAC,WAAW,CAAC,CAAA;AAC/F,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;IAAE,QAAQ,CAAC,EAAE,KAAK,CAAA;CAAE,GAAG,OAAO,CAAC,SAAS,CAAC,CAAA"}
package/lib/config.js CHANGED
@@ -1,11 +1,12 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.loadConfig = exports.checkInstall = exports.validateConfig = exports.createConfig = void 0;
3
+ exports.loadConfig = exports.checkInstall = exports.validatePlugins = exports.validateConfig = exports.createConfig = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const path_1 = (0, tslib_1.__importDefault)(require("path"));
6
6
  const plugin_1 = require("./plugin");
7
7
  const conflict_1 = require("./conflict");
8
8
  const error_1 = require("@dotcom-tool-kit/error");
9
+ const types_1 = require("@dotcom-tool-kit/types");
9
10
  const messages_1 = require("./messages");
10
11
  const coreRoot = path_1.default.resolve(__dirname, '../');
11
12
  const createConfig = () => ({
@@ -88,6 +89,11 @@ function validateConfig(config) {
88
89
  }
89
90
  }
90
91
  exports.validateConfig = validateConfig;
92
+ function validatePlugins(config) {
93
+ const validatedPlugins = (0, types_1.reduceValidated)(Object.entries(config.plugins).map(([id, plugin]) => (0, types_1.mapValidated)(plugin, (p) => [id, p])));
94
+ return (0, types_1.mapValidated)(validatedPlugins, (plugins) => ({ ...config, plugins: Object.fromEntries(plugins) }));
95
+ }
96
+ exports.validatePlugins = validatePlugins;
91
97
  async function checkInstall(config) {
92
98
  const definedHooks = (0, conflict_1.withoutConflicts)(Object.values(config.hooks));
93
99
  const uninstalledHooks = await asyncFilter(definedHooks, async (hook) => {
@@ -104,10 +110,23 @@ async function loadConfig(logger, { validate = true } = {}) {
104
110
  const config = (0, exports.createConfig)();
105
111
  // start loading config and child plugins, starting from the consumer app directory
106
112
  const rootPlugin = await (0, plugin_1.loadPlugin)('app root', config, logger);
113
+ if (!rootPlugin.valid) {
114
+ const error = new error_1.ToolKitError('root plugin was not valid!');
115
+ error.details = rootPlugin.reasons.join('\n\n');
116
+ throw error;
117
+ }
118
+ const validRootPlugin = rootPlugin.value;
119
+ const validatedPluginConfig = validatePlugins(config);
120
+ if (!validatedPluginConfig.valid) {
121
+ const error = new error_1.ToolKitError('config was not valid!');
122
+ error.details = validatedPluginConfig.reasons.join('\n\n');
123
+ throw error;
124
+ }
125
+ const validPluginConfig = validatedPluginConfig.value;
107
126
  // collate root plugin and descendent hooks, options etc into config
108
- (0, plugin_1.resolvePlugin)(rootPlugin, config, logger);
127
+ (0, plugin_1.resolvePlugin)(validRootPlugin, validPluginConfig, logger);
109
128
  if (validate) {
110
- validateConfig(config);
129
+ validateConfig(validPluginConfig);
111
130
  }
112
131
  return config;
113
132
  }
package/lib/index.js CHANGED
@@ -76,8 +76,8 @@ exports.runTasks = runTasks;
76
76
  async function listPlugins(logger) {
77
77
  const config = await (0, config_1.loadConfig)(logger, { validate: false });
78
78
  const rootPlugin = config.plugins['app root'];
79
- if (rootPlugin) {
80
- logger.info((0, messages_1.formatPluginTree)(rootPlugin).join('\n'));
79
+ if (rootPlugin === null || rootPlugin === void 0 ? void 0 : rootPlugin.valid) {
80
+ logger.info((0, messages_1.formatPluginTree)(rootPlugin.value).join('\n'));
81
81
  }
82
82
  }
83
83
  exports.listPlugins = listPlugins;
package/lib/install.d.ts CHANGED
@@ -1,4 +1,4 @@
1
1
  import type { Logger } from 'winston';
2
- import { Config } from './config';
3
- export default function installHooks(logger: Logger): Promise<Config>;
2
+ import { ValidConfig } from './config';
3
+ export default function installHooks(logger: Logger): Promise<ValidConfig>;
4
4
  //# sourceMappingURL=install.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../src/install.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AACrC,OAAO,EAAE,MAAM,EAAc,MAAM,UAAU,CAAA;AAE7C,wBAA8B,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAqC1E"}
1
+ {"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../src/install.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AACrC,OAAO,EAAc,WAAW,EAAE,MAAM,UAAU,CAAA;AAGlD,wBAA8B,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAqC/E"}
package/lib/plugin.d.ts CHANGED
@@ -1,7 +1,7 @@
1
+ import { Plugin, PluginModule, Validated } from '@dotcom-tool-kit/types';
1
2
  import type { Logger } from 'winston';
2
- import { Config } from './config';
3
- import { Plugin, PluginModule } from '@dotcom-tool-kit/types';
4
- export declare function validatePlugin(plugin: unknown): asserts plugin is PluginModule;
5
- export declare function loadPlugin(id: string, config: Config, logger: Logger, parent?: Plugin): Promise<Plugin>;
6
- export declare function resolvePlugin(plugin: Plugin, config: Config, logger: Logger): void;
3
+ import { RawConfig, ValidPluginsConfig } from './config';
4
+ export declare function validatePlugin(plugin: unknown): Validated<PluginModule>;
5
+ export declare function loadPlugin(id: string, config: RawConfig, logger: Logger, parent?: Plugin): Promise<Validated<Plugin>>;
6
+ export declare function resolvePlugin(plugin: Plugin, config: ValidPluginsConfig, logger: Logger): void;
7
7
  //# sourceMappingURL=plugin.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AAGrC,OAAO,EAAE,MAAM,EAAiB,MAAM,UAAU,CAAA;AAIhD,OAAO,EAAQ,MAAM,EAAE,YAAY,EAAQ,MAAM,wBAAwB,CAAA;AAezE,wBAAgB,cAAc,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,IAAI,YAAY,CAmB9E;AASD,wBAAsB,UAAU,CAC9B,EAAE,EAAE,MAAM,EACV,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,MAAM,CAAC,CAmCjB;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAsIlF"}
1
+ {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AACA,OAAO,EAKL,MAAM,EACN,YAAY,EAIZ,SAAS,EACV,MAAM,wBAAwB,CAAA;AAG/B,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AACrC,OAAO,EAAiB,SAAS,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAA;AAmBvE,wBAAgB,cAAc,CAAC,MAAM,EAAE,OAAO,GAAG,SAAS,CAAC,YAAY,CAAC,CAgDvE;AAoBD,wBAAsB,UAAU,CAC9B,EAAE,EAAE,MAAM,EACV,MAAM,EAAE,SAAS,EACjB,MAAM,EAAE,MAAM,EACd,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAyD5B;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,kBAAkB,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAsI9F"}
package/lib/plugin.js CHANGED
@@ -2,12 +2,12 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.resolvePlugin = exports.loadPlugin = exports.validatePlugin = void 0;
4
4
  const tslib_1 = require("tslib");
5
+ const logger_1 = require("@dotcom-tool-kit/logger");
6
+ const types_1 = require("@dotcom-tool-kit/types");
7
+ const lodash_isplainobject_1 = (0, tslib_1.__importDefault)(require("lodash.isplainobject"));
5
8
  const resolve_from_1 = (0, tslib_1.__importDefault)(require("resolve-from"));
6
9
  const conflict_1 = require("./conflict");
7
10
  const rc_file_1 = require("./rc-file");
8
- const error_1 = require("@dotcom-tool-kit/error");
9
- const types_1 = require("@dotcom-tool-kit/types");
10
- const lodash_isplainobject_1 = (0, tslib_1.__importDefault)(require("lodash.isplainobject"));
11
11
  function isDescendent(possibleAncestor, possibleDescendent) {
12
12
  if (!possibleDescendent.parent) {
13
13
  return false;
@@ -19,24 +19,61 @@ function isDescendent(possibleAncestor, possibleDescendent) {
19
19
  return isDescendent(possibleAncestor, possibleDescendent.parent);
20
20
  }
21
21
  }
22
+ const indentReasons = (reasons) => reasons.replace(/\n/g, '\n ');
22
23
  function validatePlugin(plugin) {
24
+ var _a, _b;
25
+ const errors = [];
23
26
  const rawPlugin = plugin;
24
- if (rawPlugin.tasks &&
25
- !(Array.isArray(rawPlugin.tasks) && rawPlugin.tasks.every((task) => task.prototype instanceof types_1.Task))) {
26
- throw new error_1.ToolKitError('tasks are not valid');
27
+ if (rawPlugin.tasks) {
28
+ if (!Array.isArray(rawPlugin.tasks)) {
29
+ errors.push(`the exported ${logger_1.styles.code('tasks')} value from this plugin is not an array`);
30
+ }
31
+ else {
32
+ const validatedTasks = (0, types_1.reduceValidated)(rawPlugin.tasks.map((task) => (0, types_1.mapValidationError)(types_1.Task.isCompatible(task), (reasons) => [
33
+ `the task ${logger_1.styles.task(task.name)} is not a compatible instance of ${logger_1.styles.code('Task')}:\n - ${reasons.join('\n - ')}`
34
+ ])));
35
+ if (!validatedTasks.valid) {
36
+ errors.push(...validatedTasks.reasons);
37
+ }
38
+ }
39
+ }
40
+ if (rawPlugin.hooks) {
41
+ if (!(0, lodash_isplainobject_1.default)(rawPlugin.hooks)) {
42
+ errors.push(`the exported ${logger_1.styles.code('hooks')} value from this plugin is not an object`);
43
+ }
44
+ else {
45
+ const validatedHooks = (0, types_1.reduceValidated)(Object.entries(rawPlugin.hooks).map(([id, hook]) => (0, types_1.mapValidationError)(types_1.Hook.isCompatible(hook), (reasons) => [
46
+ `the hook ${logger_1.styles.hook(id)} is not a compatible instance of ${logger_1.styles.code('Hook')}:\n - ${reasons.join('\n - ')}`
47
+ ])));
48
+ if (!validatedHooks.valid) {
49
+ errors.push(...validatedHooks.reasons);
50
+ }
51
+ }
27
52
  }
28
- if (rawPlugin.hooks &&
29
- !((0, lodash_isplainobject_1.default)(rawPlugin.hooks) &&
30
- Object.values(rawPlugin.hooks).every((hook) => hook.prototype instanceof types_1.Hook))) {
31
- throw new error_1.ToolKitError('hooks are not valid');
53
+ if (errors.length > 0) {
54
+ return { valid: false, reasons: errors };
55
+ }
56
+ else {
57
+ const pluginModule = { tasks: (_a = rawPlugin.tasks) !== null && _a !== void 0 ? _a : [], hooks: (_b = rawPlugin.hooks) !== null && _b !== void 0 ? _b : {} };
58
+ return { valid: true, value: pluginModule };
32
59
  }
33
60
  }
34
61
  exports.validatePlugin = validatePlugin;
35
62
  async function importPlugin(pluginPath) {
36
- // pluginPath is an absolute resolved path to a plugin module as found from its parent
37
- const pluginModule = await Promise.resolve().then(() => (0, tslib_1.__importStar)(require(pluginPath)));
38
- validatePlugin(pluginModule);
39
- return pluginModule;
63
+ try {
64
+ // pluginPath is an absolute resolved path to a plugin module as found from its parent
65
+ const pluginModule = (await Promise.resolve().then(() => (0, tslib_1.__importStar)(require(pluginPath))));
66
+ return validatePlugin(pluginModule);
67
+ }
68
+ catch (e) {
69
+ const err = e;
70
+ return {
71
+ valid: false,
72
+ reasons: [
73
+ `an error was thrown when loading this plugin's entrypoint:\n ${logger_1.styles.code(indentReasons(err.toString()))}`
74
+ ]
75
+ };
76
+ }
40
77
  }
41
78
  async function loadPlugin(id, config, logger, parent) {
42
79
  // don't load duplicate plugins
@@ -45,22 +82,44 @@ async function loadPlugin(id, config, logger, parent) {
45
82
  }
46
83
  // load plugin relative to the parent plugin
47
84
  const root = parent ? parent.root : process.cwd();
48
- const pluginRoot = id === 'app root' ? root : (0, resolve_from_1.default)(root, id);
85
+ let pluginRoot;
86
+ try {
87
+ pluginRoot = id === 'app root' ? root : (0, resolve_from_1.default)(root, id);
88
+ }
89
+ catch (e) {
90
+ return { valid: false, reasons: [`could not find path for name ${logger_1.styles.filepath(id)}`] };
91
+ }
49
92
  const plugin = {
50
- id,
51
- root: pluginRoot,
52
- parent
93
+ valid: true,
94
+ value: {
95
+ id,
96
+ root: pluginRoot,
97
+ parent
98
+ }
53
99
  };
54
100
  config.plugins[id] = plugin;
55
101
  // start loading rc file in the background
56
102
  const rcFilePromise = (0, rc_file_1.loadToolKitRC)(pluginRoot);
57
103
  // start loading module in the background
58
- const pluginModulePromise = id === 'app root' ? Promise.resolve(undefined) : importPlugin(pluginRoot);
59
- plugin.rcFile = await rcFilePromise;
104
+ const pluginModulePromise = id === 'app root' ? Promise.resolve({ valid: true, value: undefined }) : importPlugin(pluginRoot);
105
+ plugin.value.rcFile = await rcFilePromise;
60
106
  // start loading child plugins in the background
61
- const childrenPromise = Promise.all(plugin.rcFile.plugins.map((child) => loadPlugin(child, config, logger, plugin)));
62
- [plugin.module, plugin.children] = await Promise.all([pluginModulePromise, childrenPromise]);
63
- return plugin;
107
+ const childrenPromise = Promise.all(plugin.value.rcFile.plugins.map((child) => loadPlugin(child, config, logger, plugin.value)));
108
+ // wait for pending promises concurrently
109
+ const [module, children] = await Promise.all([pluginModulePromise, childrenPromise]);
110
+ const validatedModule = (0, types_1.mapValidationError)(module, (reasons) => [
111
+ indentReasons(`plugin ${logger_1.styles.plugin(id)} failed to load because:\n- ${reasons.join('\n- ')}`)
112
+ ]);
113
+ const validatedChildren = (0, types_1.mapValidationError)((0, types_1.reduceValidated)(children), (reasons) => [
114
+ indentReasons(`some child plugins of ${logger_1.styles.plugin(id)} failed to load:\n- ${reasons.join('\n- ')}`)
115
+ ]);
116
+ return (0, types_1.mapValidated)((0, types_1.joinValidated)(validatedModule, validatedChildren), ([module, children]) => {
117
+ // avoid cloning the plugin value with an object spread as we do object
118
+ // reference comparisons in multiple places
119
+ plugin.value.module = module;
120
+ plugin.value.children = children;
121
+ return plugin.value;
122
+ });
64
123
  }
65
124
  exports.loadPlugin = loadPlugin;
66
125
  function resolvePlugin(plugin, config, logger) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dotcom-tool-kit",
3
- "version": "2.2.3",
3
+ "version": "2.3.2",
4
4
  "description": "modern, maintainable, modular developer tooling for FT.com projects",
5
5
  "author": "FT.com Platforms Team <platforms-team.customer-products@ft.com>",
6
6
  "license": "MIT",
@@ -23,17 +23,17 @@
23
23
  "@jest/globals": "^27.4.6",
24
24
  "@types/lodash.merge": "^4.6.6",
25
25
  "@types/node": "^12.20.24",
26
- "@dotcom-tool-kit/backend-app": "^2.0.5",
27
- "@dotcom-tool-kit/heroku": "^2.0.4",
28
- "@dotcom-tool-kit/webpack": "^2.1.2",
29
- "@dotcom-tool-kit/babel": "^2.0.3",
30
- "@dotcom-tool-kit/circleci": "^2.1.1",
31
- "@dotcom-tool-kit/npm": "^2.0.4",
32
- "@dotcom-tool-kit/circleci-heroku": "^2.0.5",
33
- "@dotcom-tool-kit/frontend-app": "^2.1.3",
34
- "@dotcom-tool-kit/eslint": "^2.1.2",
35
- "@dotcom-tool-kit/mocha": "^2.1.0",
36
- "@dotcom-tool-kit/n-test": "^2.0.4",
26
+ "@dotcom-tool-kit/backend-app": "^2.0.8",
27
+ "@dotcom-tool-kit/heroku": "^2.0.7",
28
+ "@dotcom-tool-kit/webpack": "^2.1.5",
29
+ "@dotcom-tool-kit/babel": "^2.0.6",
30
+ "@dotcom-tool-kit/circleci": "^2.1.4",
31
+ "@dotcom-tool-kit/npm": "^2.0.7",
32
+ "@dotcom-tool-kit/circleci-heroku": "^2.0.8",
33
+ "@dotcom-tool-kit/frontend-app": "^2.1.6",
34
+ "@dotcom-tool-kit/eslint": "^2.1.5",
35
+ "@dotcom-tool-kit/mocha": "^2.1.3",
36
+ "@dotcom-tool-kit/n-test": "^2.1.1",
37
37
  "chai": "^4.3.4",
38
38
  "globby": "^10.0.2",
39
39
  "ts-node": "^8.10.2",
@@ -41,9 +41,9 @@
41
41
  },
42
42
  "dependencies": {
43
43
  "@dotcom-tool-kit/error": "^2.0.0",
44
- "@dotcom-tool-kit/logger": "^2.0.0",
45
- "@dotcom-tool-kit/options": "^2.0.3",
46
- "@dotcom-tool-kit/types": "^2.3.0",
44
+ "@dotcom-tool-kit/logger": "^2.1.1",
45
+ "@dotcom-tool-kit/options": "^2.0.6",
46
+ "@dotcom-tool-kit/types": "^2.5.1",
47
47
  "@dotcom-tool-kit/wait-for-ok": "^2.0.0",
48
48
  "cosmiconfig": "^7.0.0",
49
49
  "lodash.merge": "^4.6.2",