dotcom-tool-kit 2.1.0 → 2.2.1
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/bin/run +4 -2
- package/lib/config.d.ts +4 -2
- package/lib/config.d.ts.map +1 -1
- package/lib/config.js +12 -12
- package/lib/index.d.ts +1 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +10 -1
- package/lib/messages.d.ts +2 -1
- package/lib/messages.d.ts.map +1 -1
- package/lib/messages.js +15 -1
- package/lib/plugin.d.ts +4 -4
- package/lib/plugin.d.ts.map +1 -1
- package/lib/plugin.js +151 -114
- package/lib/rc-file.d.ts +1 -9
- package/lib/rc-file.d.ts.map +1 -1
- package/lib/rc-file.js +7 -2
- package/package.json +14 -6
package/bin/run
CHANGED
|
@@ -1,17 +1,19 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
const argv = require('minimist')(process.argv.slice(2), {
|
|
4
|
-
boolean: ['help', 'install'],
|
|
4
|
+
boolean: ['help', 'install', 'listPlugins'],
|
|
5
5
|
'--': true
|
|
6
6
|
})
|
|
7
7
|
|
|
8
|
-
const { runTasks, showHelp, installHooks } = require('../lib')
|
|
8
|
+
const { runTasks, showHelp, installHooks, listPlugins } = require('../lib')
|
|
9
9
|
const { rootLogger, styles } = require('@dotcom-tool-kit/logger')
|
|
10
10
|
|
|
11
11
|
async function main() {
|
|
12
12
|
try {
|
|
13
13
|
if (argv.install) {
|
|
14
14
|
await installHooks(rootLogger)
|
|
15
|
+
} else if (argv.listPlugins) {
|
|
16
|
+
await listPlugins(rootLogger)
|
|
15
17
|
} else if (argv.help || argv._.length === 0) {
|
|
16
18
|
await showHelp(rootLogger, argv._)
|
|
17
19
|
} else {
|
package/lib/config.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { Logger } from 'winston';
|
|
2
2
|
import type { HookTask } from './hook';
|
|
3
3
|
import { Conflict } from './conflict';
|
|
4
|
-
import
|
|
4
|
+
import { TaskClass, Hook, Plugin } from '@dotcom-tool-kit/types';
|
|
5
5
|
export interface PluginOptions {
|
|
6
6
|
options: Record<string, unknown>;
|
|
7
7
|
plugin: Plugin;
|
|
@@ -12,6 +12,7 @@ export interface Config {
|
|
|
12
12
|
plugins: {
|
|
13
13
|
[id: string]: Plugin;
|
|
14
14
|
};
|
|
15
|
+
resolvedPlugins: Set<Plugin>;
|
|
15
16
|
tasks: {
|
|
16
17
|
[id: string]: TaskClass | Conflict<TaskClass>;
|
|
17
18
|
};
|
|
@@ -39,7 +40,8 @@ export interface ValidConfig extends Config {
|
|
|
39
40
|
[id: string]: Hook;
|
|
40
41
|
};
|
|
41
42
|
}
|
|
42
|
-
export declare
|
|
43
|
+
export declare const createConfig: () => Config;
|
|
44
|
+
export declare function validateConfig(config: Config): asserts config is ValidConfig;
|
|
43
45
|
export declare function checkInstall(config: ValidConfig): Promise<void>;
|
|
44
46
|
export declare function loadConfig(logger: Logger, options?: {
|
|
45
47
|
validate?: true;
|
package/lib/config.d.ts.map
CHANGED
|
@@ -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,
|
|
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"}
|
package/lib/config.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.loadConfig = exports.checkInstall = exports.validateConfig = void 0;
|
|
3
|
+
exports.loadConfig = exports.checkInstall = 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");
|
|
@@ -11,16 +11,18 @@ const coreRoot = path_1.default.resolve(__dirname, '../');
|
|
|
11
11
|
const createConfig = () => ({
|
|
12
12
|
root: coreRoot,
|
|
13
13
|
plugins: {},
|
|
14
|
+
resolvedPlugins: new Set(),
|
|
14
15
|
tasks: {},
|
|
15
16
|
hookTasks: {},
|
|
16
17
|
options: {},
|
|
17
18
|
hooks: {}
|
|
18
19
|
});
|
|
20
|
+
exports.createConfig = createConfig;
|
|
19
21
|
async function asyncFilter(items, predicate) {
|
|
20
22
|
const results = await Promise.all(items.map(async (item) => ({ item, keep: await predicate(item) })));
|
|
21
23
|
return results.filter(({ keep }) => keep).map(({ item }) => item);
|
|
22
24
|
}
|
|
23
|
-
|
|
25
|
+
function validateConfig(config) {
|
|
24
26
|
const hookTaskConflicts = (0, conflict_1.findConflicts)(Object.values(config.hookTasks));
|
|
25
27
|
const hookConflicts = (0, conflict_1.findConflicts)(Object.values(config.hooks));
|
|
26
28
|
const taskConflicts = (0, conflict_1.findConflicts)(Object.values(config.tasks));
|
|
@@ -84,7 +86,6 @@ async function validateConfig(config) {
|
|
|
84
86
|
if (shouldThrow) {
|
|
85
87
|
throw error;
|
|
86
88
|
}
|
|
87
|
-
return config;
|
|
88
89
|
}
|
|
89
90
|
exports.validateConfig = validateConfig;
|
|
90
91
|
async function checkInstall(config) {
|
|
@@ -100,15 +101,14 @@ async function checkInstall(config) {
|
|
|
100
101
|
}
|
|
101
102
|
exports.checkInstall = checkInstall;
|
|
102
103
|
async function loadConfig(logger, { validate = true } = {}) {
|
|
104
|
+
const config = (0, exports.createConfig)();
|
|
103
105
|
// start loading config and child plugins, starting from the consumer app directory
|
|
104
|
-
const
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
106
|
+
const rootPlugin = await (0, plugin_1.loadPlugin)('app root', config, logger);
|
|
107
|
+
// collate root plugin and descendent hooks, options etc into config
|
|
108
|
+
(0, plugin_1.resolvePlugin)(rootPlugin, config, logger);
|
|
109
|
+
if (validate) {
|
|
110
|
+
validateConfig(config);
|
|
111
|
+
}
|
|
112
|
+
return config;
|
|
109
113
|
}
|
|
110
114
|
exports.loadConfig = loadConfig;
|
|
111
|
-
// abstract class TestBase {}
|
|
112
|
-
// class Test extends TestBase {}
|
|
113
|
-
// const testBase = TestBase
|
|
114
|
-
// const test = new testBase()
|
package/lib/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Logger } from 'winston';
|
|
2
2
|
export declare function runTasks(logger: Logger, hooks: string[], files?: string[]): Promise<void>;
|
|
3
|
+
export declare function listPlugins(logger: Logger): Promise<void>;
|
|
3
4
|
export { default as showHelp } from './help';
|
|
4
5
|
export { default as installHooks } from './install';
|
|
5
6
|
//# sourceMappingURL=index.d.ts.map
|
package/lib/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AASrC,wBAAsB,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,KAAK,CAAC,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CA8E/F;AAED,wBAAsB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAO/D;AAED,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,QAAQ,CAAA;AAC5C,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,WAAW,CAAA"}
|
package/lib/index.js
CHANGED
|
@@ -3,11 +3,12 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.installHooks = exports.showHelp = exports.runTasks = void 0;
|
|
6
|
+
exports.installHooks = exports.showHelp = exports.listPlugins = exports.runTasks = void 0;
|
|
7
7
|
const error_1 = require("@dotcom-tool-kit/error");
|
|
8
8
|
const config_1 = require("./config");
|
|
9
9
|
const options_1 = require("@dotcom-tool-kit/options");
|
|
10
10
|
const logger_1 = require("@dotcom-tool-kit/logger");
|
|
11
|
+
const messages_1 = require("./messages");
|
|
11
12
|
async function runTasks(logger, hooks, files) {
|
|
12
13
|
const config = await (0, config_1.loadConfig)(logger);
|
|
13
14
|
const availableHooks = Object.keys(config.hooks)
|
|
@@ -72,6 +73,14 @@ ${error.details}`
|
|
|
72
73
|
}
|
|
73
74
|
}
|
|
74
75
|
exports.runTasks = runTasks;
|
|
76
|
+
async function listPlugins(logger) {
|
|
77
|
+
const config = await (0, config_1.loadConfig)(logger, { validate: false });
|
|
78
|
+
const rootPlugin = config.plugins['app root'];
|
|
79
|
+
if (rootPlugin) {
|
|
80
|
+
logger.info((0, messages_1.formatPluginTree)(rootPlugin).join('\n'));
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
exports.listPlugins = listPlugins;
|
|
75
84
|
var help_1 = require("./help");
|
|
76
85
|
Object.defineProperty(exports, "showHelp", { enumerable: true, get: function () { return __importDefault(help_1).default; } });
|
|
77
86
|
var install_1 = require("./install");
|
package/lib/messages.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { PluginOptions } from './config';
|
|
2
2
|
import type { Conflict } from './conflict';
|
|
3
3
|
import type { HookTask } from './hook';
|
|
4
|
-
import type { Hook, TaskClass } from '@dotcom-tool-kit/types';
|
|
4
|
+
import type { Plugin, Hook, TaskClass } from '@dotcom-tool-kit/types';
|
|
5
5
|
export declare const formatTaskConflicts: (conflicts: Conflict<TaskClass>[]) => string;
|
|
6
6
|
export declare const formatHookConflicts: (conflicts: Conflict<Hook>[]) => string;
|
|
7
7
|
export declare const formatHookTaskConflicts: (conflicts: Conflict<HookTask>[]) => string;
|
|
@@ -14,5 +14,6 @@ declare type Missing = {
|
|
|
14
14
|
tasks: string[];
|
|
15
15
|
};
|
|
16
16
|
export declare const formatMissingTasks: (missingTasks: Missing[], tasks: string[]) => string;
|
|
17
|
+
export declare function formatPluginTree(plugin: Plugin): string[];
|
|
17
18
|
export {};
|
|
18
19
|
//# sourceMappingURL=messages.d.ts.map
|
package/lib/messages.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"messages.d.ts","sourceRoot":"","sources":["../src/messages.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AAC7C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAC1C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAA;AAEtC,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"messages.d.ts","sourceRoot":"","sources":["../src/messages.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AAC7C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAC1C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAA;AAEtC,OAAO,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAA;AASrE,eAAO,MAAM,mBAAmB,cAAe,SAAS,SAAS,CAAC,EAAE,KAAG,MAKE,CAAA;AASzE,eAAO,MAAM,mBAAmB,cAAe,SAAS,IAAI,CAAC,EAAE,KAAG,MAKO,CAAA;AAazE,eAAO,MAAM,uBAAuB,cAAe,SAAS,QAAQ,CAAC,EAAE,KAAG,MAQzE,CAAA;AAOD,eAAO,MAAM,qBAAqB,cAAe,SAAS,aAAa,CAAC,EAAE,KAAG,MAU5E,CAAA;AAMD,eAAO,MAAM,wBAAwB,mBACnB,QAAQ,EAAE,gBACZ,MAAM,EAAE,KACrB,MAWF,CAAA;AAED,eAAO,MAAM,mBAAmB,kBACf,MAAM,EAAE,kBACP,MAAM,EAAE,KACvB,MAWF,CAAA;AAED,eAAO,MAAM,sBAAsB,qBACf,IAAI,EAAE,KACvB,MAKF,CAAA;AAED,aAAK,OAAO,GAAG;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,KAAK,EAAE,MAAM,EAAE,CAAA;CAAE,CAAA;AAOlD,eAAO,MAAM,kBAAkB,iBACf,OAAO,EAAE,SAChB,MAAM,EAAE,KACd,MAOF,CAAA;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAezD"}
|
package/lib/messages.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.formatMissingTasks = exports.formatUninstalledHooks = exports.formatUnusedOptions = exports.formatUndefinedHookTasks = exports.formatOptionConflicts = exports.formatHookTaskConflicts = exports.formatHookConflicts = exports.formatTaskConflicts = void 0;
|
|
3
|
+
exports.formatPluginTree = exports.formatMissingTasks = exports.formatUninstalledHooks = exports.formatUnusedOptions = exports.formatUndefinedHookTasks = exports.formatOptionConflicts = exports.formatHookTaskConflicts = exports.formatHookConflicts = exports.formatTaskConflicts = void 0;
|
|
4
4
|
const logger_1 = require("@dotcom-tool-kit/logger");
|
|
5
5
|
const formatTaskConflict = (conflict) => `- ${logger_1.styles.task(conflict.conflicting[0].id || 'unknown task')} ${logger_1.styles.dim('from plugins')} ${conflict.conflicting
|
|
6
6
|
.map((task) => logger_1.styles.plugin(task.plugin ? task.plugin.id : 'unknown plugin'))
|
|
@@ -80,3 +80,17 @@ They could be misspelt, or defined by a Tool Kit plugin that isn't used by this
|
|
|
80
80
|
Available tasks are: ${tasks.map(logger_1.styles.task).join(', ')}.
|
|
81
81
|
`;
|
|
82
82
|
exports.formatMissingTasks = formatMissingTasks;
|
|
83
|
+
function formatPluginTree(plugin) {
|
|
84
|
+
var _a;
|
|
85
|
+
return [
|
|
86
|
+
logger_1.styles.plugin(plugin.id),
|
|
87
|
+
...((_a = plugin.children) !== null && _a !== void 0 ? _a : []).flatMap((child, childIndex, children) => formatPluginTree(child).map((line, lineIndex) => lineIndex === 0
|
|
88
|
+
? childIndex === children.length - 1
|
|
89
|
+
? `└ ${line}`
|
|
90
|
+
: `├ ${line}`
|
|
91
|
+
: childIndex === children.length - 1
|
|
92
|
+
? ` ${line}`
|
|
93
|
+
: `│ ${line}`))
|
|
94
|
+
];
|
|
95
|
+
}
|
|
96
|
+
exports.formatPluginTree = formatPluginTree;
|
package/lib/plugin.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { Logger } from 'winston';
|
|
2
2
|
import { Config } from './config';
|
|
3
|
-
import { Plugin } from '@dotcom-tool-kit/types';
|
|
4
|
-
export declare function
|
|
5
|
-
export declare function loadPlugin(
|
|
6
|
-
export declare function
|
|
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;
|
|
7
7
|
//# sourceMappingURL=plugin.d.ts.map
|
package/lib/plugin.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"
|
|
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"}
|
package/lib/plugin.js
CHANGED
|
@@ -1,15 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.resolvePlugin = exports.loadPlugin = exports.validatePlugin = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
|
-
const import_from_1 = (0, tslib_1.__importDefault)(require("import-from"));
|
|
6
5
|
const resolve_from_1 = (0, tslib_1.__importDefault)(require("resolve-from"));
|
|
7
|
-
const lodash_mergewith_1 = (0, tslib_1.__importDefault)(require("lodash.mergewith"));
|
|
8
6
|
const conflict_1 = require("./conflict");
|
|
9
7
|
const rc_file_1 = require("./rc-file");
|
|
10
8
|
const error_1 = require("@dotcom-tool-kit/error");
|
|
11
|
-
const logger_1 = require("@dotcom-tool-kit/logger");
|
|
12
9
|
const types_1 = require("@dotcom-tool-kit/types");
|
|
10
|
+
const lodash_isplainobject_1 = (0, tslib_1.__importDefault)(require("lodash.isplainobject"));
|
|
13
11
|
function isDescendent(possibleAncestor, possibleDescendent) {
|
|
14
12
|
if (!possibleDescendent.parent) {
|
|
15
13
|
return false;
|
|
@@ -21,129 +19,168 @@ function isDescendent(possibleAncestor, possibleDescendent) {
|
|
|
21
19
|
return isDescendent(possibleAncestor, possibleDescendent.parent);
|
|
22
20
|
}
|
|
23
21
|
}
|
|
24
|
-
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
plugin,
|
|
36
|
-
tasks: Array.isArray(configHookTask) ? configHookTask : [configHookTask]
|
|
37
|
-
};
|
|
38
|
-
// this hook task might not have been set yet, in which case use the new one
|
|
39
|
-
if (!existingHookTask) {
|
|
40
|
-
return newHookTask;
|
|
41
|
-
}
|
|
42
|
-
const existingFromDescendent = isDescendent(plugin, existingHookTask.plugin);
|
|
43
|
-
// plugins can only override hook tasks from their descendents, otherwise that's a conflict
|
|
44
|
-
// return a conflict either listing this hook and the siblings,
|
|
45
|
-
// or merging in a previously-generated hook
|
|
46
|
-
if (!existingFromDescendent) {
|
|
47
|
-
const conflicting = (0, conflict_1.isConflict)(existingHookTask) ? existingHookTask.conflicting : [existingHookTask];
|
|
48
|
-
const conflict = {
|
|
49
|
-
plugin,
|
|
50
|
-
conflicting: conflicting.concat(newHookTask)
|
|
51
|
-
};
|
|
52
|
-
return conflict;
|
|
53
|
-
}
|
|
54
|
-
// if we're here, any existing hook is from a child plugin,
|
|
55
|
-
// so the parent always overrides it
|
|
56
|
-
return newHookTask;
|
|
57
|
-
});
|
|
58
|
-
// merge options from this plugin's config with any options we've collected already
|
|
59
|
-
// TODO this is almost the exact same code as for hooks, refactor
|
|
60
|
-
(0, lodash_mergewith_1.default)(config.options, options, (existingOptions, configOptions, id) => {
|
|
61
|
-
const pluginOptions = {
|
|
62
|
-
options: configOptions,
|
|
63
|
-
plugin,
|
|
64
|
-
forPlugin: config.plugins[id]
|
|
65
|
-
};
|
|
66
|
-
// this options key might not have been set yet, in which case use the new one
|
|
67
|
-
if (!existingOptions) {
|
|
68
|
-
return pluginOptions;
|
|
69
|
-
}
|
|
70
|
-
const existingFromDescendent = isDescendent(plugin, existingOptions.plugin);
|
|
71
|
-
// plugins can only override options from their descendents, otherwise it's a conflict
|
|
72
|
-
// return a conflict either listing these options and the sibling's,
|
|
73
|
-
// or merging in previously-generated options
|
|
74
|
-
if (!existingFromDescendent) {
|
|
75
|
-
const conflicting = (0, conflict_1.isConflict)(existingOptions) ? existingOptions.conflicting : [existingOptions];
|
|
76
|
-
const conflict = {
|
|
77
|
-
plugin,
|
|
78
|
-
conflicting: conflicting.concat(pluginOptions)
|
|
79
|
-
};
|
|
80
|
-
return conflict;
|
|
81
|
-
}
|
|
82
|
-
// if we're here, any existing options are from a child plugin,
|
|
83
|
-
// so merge in overrides from the parent
|
|
84
|
-
return { ...existingOptions, ...pluginOptions };
|
|
85
|
-
});
|
|
86
|
-
return config;
|
|
22
|
+
function validatePlugin(plugin) {
|
|
23
|
+
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
|
+
}
|
|
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');
|
|
32
|
+
}
|
|
87
33
|
}
|
|
88
|
-
exports.
|
|
89
|
-
async function
|
|
34
|
+
exports.validatePlugin = validatePlugin;
|
|
35
|
+
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;
|
|
40
|
+
}
|
|
41
|
+
async function loadPlugin(id, config, logger, parent) {
|
|
90
42
|
// don't load duplicate plugins
|
|
91
43
|
if (id in config.plugins) {
|
|
92
44
|
return config.plugins[id];
|
|
93
45
|
}
|
|
94
|
-
const root = parent ? parent.root : process.cwd();
|
|
95
46
|
// load plugin relative to the parent plugin
|
|
96
|
-
const
|
|
97
|
-
const
|
|
98
|
-
let basePlugin;
|
|
99
|
-
try {
|
|
100
|
-
basePlugin = (0, types_1.instantiatePlugin)(rawPlugin, logger);
|
|
101
|
-
}
|
|
102
|
-
catch (error) {
|
|
103
|
-
if (error instanceof error_1.ToolKitError) {
|
|
104
|
-
error.details = `the package ${logger_1.styles.plugin(id)} at ${logger_1.styles.filepath(pluginRoot)} is not a valid plugin`;
|
|
105
|
-
}
|
|
106
|
-
throw error;
|
|
107
|
-
}
|
|
47
|
+
const root = parent ? parent.root : process.cwd();
|
|
48
|
+
const pluginRoot = id === 'app root' ? root : (0, resolve_from_1.default)(root, id);
|
|
108
49
|
const plugin = {
|
|
109
|
-
...basePlugin,
|
|
110
50
|
id,
|
|
111
51
|
root: pluginRoot,
|
|
112
52
|
parent
|
|
113
53
|
};
|
|
114
54
|
config.plugins[id] = plugin;
|
|
115
|
-
//
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
return {
|
|
124
|
-
plugin,
|
|
125
|
-
conflicting: conflicting.concat(newTask)
|
|
126
|
-
};
|
|
127
|
-
});
|
|
128
|
-
// add hooks to the registry, handling any conflicts
|
|
129
|
-
// TODO refactor with command conflict handler
|
|
130
|
-
(0, lodash_mergewith_1.default)(config.hooks, plugin.hooks, (existingHook, newHook, hookId) => {
|
|
131
|
-
newHook.id = hookId;
|
|
132
|
-
newHook.plugin = plugin;
|
|
133
|
-
if (!existingHook) {
|
|
134
|
-
return newHook;
|
|
135
|
-
}
|
|
136
|
-
const conflicting = (0, conflict_1.isConflict)(existingHook) ? existingHook.conflicting : [existingHook];
|
|
137
|
-
return {
|
|
138
|
-
plugin,
|
|
139
|
-
conflicting: conflicting.concat(newHook)
|
|
140
|
-
};
|
|
141
|
-
});
|
|
142
|
-
await loadPluginConfig(logger, plugin, config);
|
|
55
|
+
// start loading rc file in the background
|
|
56
|
+
const rcFilePromise = (0, rc_file_1.loadToolKitRC)(pluginRoot);
|
|
57
|
+
// start loading module in the background
|
|
58
|
+
const pluginModulePromise = id === 'app root' ? Promise.resolve(undefined) : importPlugin(pluginRoot);
|
|
59
|
+
plugin.rcFile = await rcFilePromise;
|
|
60
|
+
// 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]);
|
|
143
63
|
return plugin;
|
|
144
64
|
}
|
|
145
65
|
exports.loadPlugin = loadPlugin;
|
|
146
|
-
function
|
|
147
|
-
|
|
66
|
+
function resolvePlugin(plugin, config, logger) {
|
|
67
|
+
// don't resolve plugins that have already been resolved to prevent self-conflicts
|
|
68
|
+
// between plugins included at multiple points in the tree
|
|
69
|
+
if (config.resolvedPlugins.has(plugin)) {
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
if (plugin.children) {
|
|
73
|
+
// resolve child plugins first so parents can override the things their children set
|
|
74
|
+
for (const child of plugin.children) {
|
|
75
|
+
resolvePlugin(child, config, logger);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
if (plugin.module) {
|
|
79
|
+
// add plugin tasks to our task registry, handling any conflicts
|
|
80
|
+
for (const newTask of plugin.module.tasks || []) {
|
|
81
|
+
const taskId = newTask.name;
|
|
82
|
+
const existingTask = config.tasks[taskId];
|
|
83
|
+
newTask.plugin = plugin;
|
|
84
|
+
newTask.id = taskId;
|
|
85
|
+
if (existingTask) {
|
|
86
|
+
const conflicting = (0, conflict_1.isConflict)(existingTask) ? existingTask.conflicting : [existingTask];
|
|
87
|
+
config.tasks[taskId] = {
|
|
88
|
+
plugin,
|
|
89
|
+
conflicting: conflicting.concat(newTask)
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
config.tasks[taskId] = newTask;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
// add hooks to the registry, handling any conflicts
|
|
97
|
+
// TODO refactor with command conflict handler
|
|
98
|
+
for (const [hookId, hookClass] of Object.entries(plugin.module.hooks || [])) {
|
|
99
|
+
const existingHook = config.hooks[hookId];
|
|
100
|
+
const newHook = new hookClass(logger);
|
|
101
|
+
newHook.id = hookId;
|
|
102
|
+
newHook.plugin = plugin;
|
|
103
|
+
if (existingHook) {
|
|
104
|
+
const conflicting = (0, conflict_1.isConflict)(existingHook) ? existingHook.conflicting : [existingHook];
|
|
105
|
+
config.hooks[hookId] = {
|
|
106
|
+
plugin,
|
|
107
|
+
conflicting: conflicting.concat(newHook)
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
config.hooks[hookId] = newHook;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
if (plugin.rcFile) {
|
|
116
|
+
// load plugin hook tasks. do this after loading child plugins, so
|
|
117
|
+
// parent hooks get assigned after child hooks and can override them
|
|
118
|
+
for (const [id, configHookTask] of Object.entries(plugin.rcFile.hooks)) {
|
|
119
|
+
// handle conflicts between hooks from different plugins
|
|
120
|
+
const existingHookTask = config.hookTasks[id];
|
|
121
|
+
const newHookTask = {
|
|
122
|
+
id,
|
|
123
|
+
plugin,
|
|
124
|
+
tasks: Array.isArray(configHookTask) ? configHookTask : [configHookTask]
|
|
125
|
+
};
|
|
126
|
+
if (existingHookTask) {
|
|
127
|
+
const existingFromDescendent = isDescendent(plugin, existingHookTask.plugin);
|
|
128
|
+
// plugins can only override hook tasks from their descendents, otherwise that's a conflict
|
|
129
|
+
// return a conflict either listing this hook and the siblings,
|
|
130
|
+
// or merging in a previously-generated hook
|
|
131
|
+
if (!existingFromDescendent) {
|
|
132
|
+
const conflicting = (0, conflict_1.isConflict)(existingHookTask) ? existingHookTask.conflicting : [existingHookTask];
|
|
133
|
+
const conflict = {
|
|
134
|
+
plugin,
|
|
135
|
+
conflicting: conflicting.concat(newHookTask)
|
|
136
|
+
};
|
|
137
|
+
config.hookTasks[id] = conflict;
|
|
138
|
+
}
|
|
139
|
+
else {
|
|
140
|
+
// if we're here, any existing hook is from a child plugin,
|
|
141
|
+
// so the parent always overrides it
|
|
142
|
+
config.hookTasks[id] = newHookTask;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
// this hook task might not have been set yet, in which case use the new one
|
|
147
|
+
config.hookTasks[id] = newHookTask;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
// merge options from this plugin's config with any options we've collected already
|
|
151
|
+
// TODO this is almost the exact same code as for hooks, refactor
|
|
152
|
+
for (const [id, configOptions] of Object.entries(plugin.rcFile.options)) {
|
|
153
|
+
const existingOptions = config.options[id];
|
|
154
|
+
const pluginOptions = {
|
|
155
|
+
options: configOptions,
|
|
156
|
+
plugin,
|
|
157
|
+
forPlugin: config.plugins[id]
|
|
158
|
+
};
|
|
159
|
+
if (existingOptions) {
|
|
160
|
+
const existingFromDescendent = isDescendent(plugin, existingOptions.plugin);
|
|
161
|
+
// plugins can only override options from their descendents, otherwise it's a conflict
|
|
162
|
+
// return a conflict either listing these options and the sibling's,
|
|
163
|
+
// or merging in previously-generated options
|
|
164
|
+
if (!existingFromDescendent) {
|
|
165
|
+
const conflicting = (0, conflict_1.isConflict)(existingOptions) ? existingOptions.conflicting : [existingOptions];
|
|
166
|
+
const conflict = {
|
|
167
|
+
plugin,
|
|
168
|
+
conflicting: conflicting.concat(pluginOptions)
|
|
169
|
+
};
|
|
170
|
+
config.options[id] = conflict;
|
|
171
|
+
}
|
|
172
|
+
else {
|
|
173
|
+
// if we're here, any existing options are from a child plugin,
|
|
174
|
+
// so merge in overrides from the parent
|
|
175
|
+
config.options[id] = { ...existingOptions, ...pluginOptions };
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
else {
|
|
179
|
+
// this options key might not have been set yet, in which case use the new one
|
|
180
|
+
config.options[id] = pluginOptions;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
config.resolvedPlugins.add(plugin);
|
|
148
185
|
}
|
|
149
|
-
exports.
|
|
186
|
+
exports.resolvePlugin = resolvePlugin;
|
package/lib/rc-file.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { RCFile } from '@dotcom-tool-kit/types/src';
|
|
1
2
|
export declare const explorer: {
|
|
2
3
|
readonly search: (searchFrom?: string | undefined) => Promise<import("cosmiconfig/dist/types").CosmiconfigResult>;
|
|
3
4
|
readonly load: (filepath: string) => Promise<import("cosmiconfig/dist/types").CosmiconfigResult>;
|
|
@@ -5,14 +6,5 @@ export declare const explorer: {
|
|
|
5
6
|
readonly clearSearchCache: () => void;
|
|
6
7
|
readonly clearCaches: () => void;
|
|
7
8
|
};
|
|
8
|
-
export interface RCFile {
|
|
9
|
-
plugins: string[];
|
|
10
|
-
hooks: {
|
|
11
|
-
[id: string]: string | string[];
|
|
12
|
-
};
|
|
13
|
-
options: {
|
|
14
|
-
[id: string]: Record<string, unknown>;
|
|
15
|
-
};
|
|
16
|
-
}
|
|
17
9
|
export declare function loadToolKitRC(root: string): Promise<RCFile>;
|
|
18
10
|
//# sourceMappingURL=rc-file.d.ts.map
|
package/lib/rc-file.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rc-file.d.ts","sourceRoot":"","sources":["../src/rc-file.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"rc-file.d.ts","sourceRoot":"","sources":["../src/rc-file.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,4BAA4B,CAAA;AAEnD,eAAO,MAAM,QAAQ;;;;;;CAA6D,CAAA;AAMlF,wBAAsB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CASjE"}
|
package/lib/rc-file.js
CHANGED
|
@@ -4,9 +4,14 @@ exports.loadToolKitRC = exports.explorer = void 0;
|
|
|
4
4
|
const cosmiconfig_1 = require("cosmiconfig");
|
|
5
5
|
exports.explorer = (0, cosmiconfig_1.cosmiconfig)('toolkit', { ignoreEmptySearchPlaces: false });
|
|
6
6
|
async function loadToolKitRC(root) {
|
|
7
|
-
|
|
7
|
+
var _a, _b, _c;
|
|
8
|
+
const result = (await exports.explorer.search(root));
|
|
8
9
|
if (!result || !result.config)
|
|
9
10
|
return { plugins: [], hooks: {}, options: {} };
|
|
10
|
-
return
|
|
11
|
+
return {
|
|
12
|
+
plugins: (_a = result.config.plugins) !== null && _a !== void 0 ? _a : [],
|
|
13
|
+
hooks: (_b = result.config.hooks) !== null && _b !== void 0 ? _b : {},
|
|
14
|
+
options: (_c = result.config.options) !== null && _c !== void 0 ? _c : {}
|
|
15
|
+
};
|
|
11
16
|
}
|
|
12
17
|
exports.loadToolKitRC = loadToolKitRC;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dotcom-tool-kit",
|
|
3
|
-
"version": "2.1
|
|
3
|
+
"version": "2.2.1",
|
|
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",
|
|
@@ -22,8 +22,18 @@
|
|
|
22
22
|
"devDependencies": {
|
|
23
23
|
"@jest/globals": "^27.4.6",
|
|
24
24
|
"@types/lodash.merge": "^4.6.6",
|
|
25
|
-
"@types/lodash.mergewith": "^4.6.6",
|
|
26
25
|
"@types/node": "^12.20.24",
|
|
26
|
+
"@dotcom-tool-kit/backend-app": "^2.0.4",
|
|
27
|
+
"@dotcom-tool-kit/heroku": "^2.0.3",
|
|
28
|
+
"@dotcom-tool-kit/webpack": "^2.1.1",
|
|
29
|
+
"@dotcom-tool-kit/babel": "^2.0.2",
|
|
30
|
+
"@dotcom-tool-kit/circleci": "^2.1.0",
|
|
31
|
+
"@dotcom-tool-kit/npm": "^2.0.3",
|
|
32
|
+
"@dotcom-tool-kit/circleci-heroku": "^2.0.4",
|
|
33
|
+
"@dotcom-tool-kit/frontend-app": "^2.1.2",
|
|
34
|
+
"@dotcom-tool-kit/eslint": "^2.1.1",
|
|
35
|
+
"@dotcom-tool-kit/mocha": "^2.0.2",
|
|
36
|
+
"@dotcom-tool-kit/n-test": "^2.0.2",
|
|
27
37
|
"chai": "^4.3.4",
|
|
28
38
|
"globby": "^10.0.2",
|
|
29
39
|
"ts-node": "^8.10.2",
|
|
@@ -32,13 +42,11 @@
|
|
|
32
42
|
"dependencies": {
|
|
33
43
|
"@dotcom-tool-kit/error": "^2.0.0",
|
|
34
44
|
"@dotcom-tool-kit/logger": "^2.0.0",
|
|
35
|
-
"@dotcom-tool-kit/options": "^2.0.
|
|
36
|
-
"@dotcom-tool-kit/types": "^2.
|
|
45
|
+
"@dotcom-tool-kit/options": "^2.0.2",
|
|
46
|
+
"@dotcom-tool-kit/types": "^2.2.0",
|
|
37
47
|
"@dotcom-tool-kit/wait-for-ok": "^2.0.0",
|
|
38
48
|
"cosmiconfig": "^7.0.0",
|
|
39
|
-
"import-from": "^3.0.0",
|
|
40
49
|
"lodash.merge": "^4.6.2",
|
|
41
|
-
"lodash.mergewith": "^4.6.2",
|
|
42
50
|
"minimist": "^1.2.5",
|
|
43
51
|
"resolve-from": "^5.0.0",
|
|
44
52
|
"tslib": "^1.14.1",
|