dotcom-tool-kit 3.5.0 → 4.0.0-beta.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 +11 -1
- package/lib/config/hash.d.ts +6 -0
- package/lib/config/hash.d.ts.map +1 -0
- package/lib/config/hash.js +43 -0
- package/lib/config/validate-plugins.d.ts +4 -0
- package/lib/config/validate-plugins.d.ts.map +1 -0
- package/lib/config/validate-plugins.js +9 -0
- package/lib/config.d.ts +2 -54
- package/lib/config.d.ts.map +1 -1
- package/lib/config.js +62 -113
- package/lib/fetch.d.ts +2 -0
- package/lib/fetch.d.ts.map +1 -0
- package/lib/fetch.js +19 -0
- package/lib/help.d.ts +1 -1
- package/lib/help.d.ts.map +1 -1
- package/lib/help.js +72 -39
- package/lib/index.d.ts +3 -4
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +12 -99
- package/lib/init.d.ts +4 -0
- package/lib/init.d.ts.map +1 -0
- package/lib/init.js +16 -0
- package/lib/install.d.ts +6 -1
- package/lib/install.d.ts.map +1 -1
- package/lib/install.js +69 -13
- package/lib/messages.d.ts +14 -13
- package/lib/messages.d.ts.map +1 -1
- package/lib/messages.js +38 -27
- package/lib/plugin/entry-point.d.ts +7 -0
- package/lib/plugin/entry-point.d.ts.map +1 -0
- package/lib/plugin/entry-point.js +46 -0
- package/lib/plugin/is-descendent.d.ts +3 -0
- package/lib/plugin/is-descendent.d.ts.map +1 -0
- package/lib/plugin/is-descendent.js +15 -0
- package/lib/plugin/merge-commands.d.ts +5 -0
- package/lib/plugin/merge-commands.d.ts.map +1 -0
- package/lib/plugin/merge-commands.js +59 -0
- package/lib/plugin/merge-hooks.d.ts +4 -0
- package/lib/plugin/merge-hooks.d.ts.map +1 -0
- package/lib/plugin/merge-hooks.js +29 -0
- package/lib/plugin/merge-inits.d.ts +4 -0
- package/lib/plugin/merge-inits.d.ts.map +1 -0
- package/lib/plugin/merge-inits.js +13 -0
- package/lib/plugin/merge-plugin-options.d.ts +4 -0
- package/lib/plugin/merge-plugin-options.d.ts.map +1 -0
- package/lib/plugin/merge-plugin-options.js +46 -0
- package/lib/plugin/merge-task-options.d.ts +4 -0
- package/lib/plugin/merge-task-options.d.ts.map +1 -0
- package/lib/plugin/merge-task-options.js +43 -0
- package/lib/plugin/merge-tasks.d.ts +4 -0
- package/lib/plugin/merge-tasks.d.ts.map +1 -0
- package/lib/plugin/merge-tasks.js +27 -0
- package/lib/plugin/options.d.ts +7 -0
- package/lib/plugin/options.d.ts.map +1 -0
- package/lib/plugin/options.js +170 -0
- package/lib/plugin/reduce-installations.d.ts +7 -0
- package/lib/plugin/reduce-installations.d.ts.map +1 -0
- package/lib/plugin/reduce-installations.js +59 -0
- package/lib/plugin.d.ts +4 -3
- package/lib/plugin.d.ts.map +1 -1
- package/lib/plugin.js +56 -217
- package/lib/rc-file.d.ts +4 -9
- package/lib/rc-file.d.ts.map +1 -1
- package/lib/rc-file.js +80 -20
- package/lib/tasks.d.ts +3 -0
- package/lib/tasks.d.ts.map +1 -0
- package/lib/tasks.js +79 -0
- package/package.json +28 -22
- package/lib/conflict.d.ts +0 -9
- package/lib/conflict.d.ts.map +0 -1
- package/lib/conflict.js +0 -27
- package/lib/hook.d.ts +0 -7
- package/lib/hook.d.ts.map +0 -1
- package/lib/hook.js +0 -2
- package/lib/postInstall.d.ts +0 -7
- package/lib/postInstall.d.ts.map +0 -1
- package/lib/postInstall.js +0 -53
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"merge-hooks.d.ts","sourceRoot":"","sources":["../../src/plugin/merge-hooks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAc,MAAM,EAAE,MAAM,yBAAyB,CAAA;AACjE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AAGjE,eAAO,MAAM,UAAU,WAAY,kBAAkB,UAAU,MAAM,SAwBpE,CAAA"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.mergeHooks = void 0;
|
|
4
|
+
const conflict_1 = require("@dotcom-tool-kit/conflict");
|
|
5
|
+
const mergeHooks = (config, plugin) => {
|
|
6
|
+
if (plugin.rcFile) {
|
|
7
|
+
// add hooks to the registry, handling any conflicts
|
|
8
|
+
// TODO refactor with command conflict handler
|
|
9
|
+
for (const [hookName, hookSpec] of Object.entries(plugin.rcFile.installs || {})) {
|
|
10
|
+
const existingHookId = config.hooks[hookName];
|
|
11
|
+
const entryPoint = {
|
|
12
|
+
plugin,
|
|
13
|
+
modulePath: hookSpec.entryPoint
|
|
14
|
+
};
|
|
15
|
+
if (existingHookId) {
|
|
16
|
+
const conflicting = (0, conflict_1.isConflict)(existingHookId) ? existingHookId.conflicting : [existingHookId];
|
|
17
|
+
config.hooks[hookName] = {
|
|
18
|
+
plugin,
|
|
19
|
+
conflicting: conflicting.concat(entryPoint)
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
config.hooks[hookName] = entryPoint;
|
|
24
|
+
hookSpec.managesFiles?.forEach((file) => config.hookManagedFiles.add(file));
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
exports.mergeHooks = mergeHooks;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"merge-inits.d.ts","sourceRoot":"","sources":["../../src/plugin/merge-inits.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAA;AACrD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AAEjE,eAAO,MAAM,UAAU,WAAY,kBAAkB,UAAU,MAAM,SAUpE,CAAA"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.mergeInits = void 0;
|
|
4
|
+
const mergeInits = (config, plugin) => {
|
|
5
|
+
if (plugin.rcFile) {
|
|
6
|
+
// no conflict resolution needed; we'll just run them all ig
|
|
7
|
+
config.inits.push(...plugin.rcFile.init.map((init) => ({
|
|
8
|
+
plugin,
|
|
9
|
+
modulePath: init
|
|
10
|
+
})));
|
|
11
|
+
}
|
|
12
|
+
};
|
|
13
|
+
exports.mergeInits = mergeInits;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"merge-plugin-options.d.ts","sourceRoot":"","sources":["../../src/plugin/merge-plugin-options.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAoB,MAAM,yBAAyB,CAAA;AACvE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AAMjE,eAAO,MAAM,kBAAkB,WAAY,kBAAkB,UAAU,MAAM,SAwC5E,CAAA"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.mergePluginOptions = void 0;
|
|
4
|
+
const is_descendent_1 = require("./is-descendent");
|
|
5
|
+
const conflict_1 = require("@dotcom-tool-kit/conflict");
|
|
6
|
+
// merge options from this plugin's config with any options we've collected already
|
|
7
|
+
// TODO this is almost the exact same code as for command tasks, refactor
|
|
8
|
+
const mergePluginOptions = (config, plugin) => {
|
|
9
|
+
if (plugin.rcFile) {
|
|
10
|
+
for (const [id, configOptions] of Object.entries(plugin.rcFile.options.plugins)) {
|
|
11
|
+
// users can specify root options with the dotcom-tool-kit key to mirror
|
|
12
|
+
// the name of the root npm package
|
|
13
|
+
const pluginId = id === 'dotcom-tool-kit' ? 'app root' : id;
|
|
14
|
+
const existingOptions = config.pluginOptions[pluginId];
|
|
15
|
+
const pluginOptions = {
|
|
16
|
+
options: configOptions,
|
|
17
|
+
plugin,
|
|
18
|
+
forPlugin: config.plugins[pluginId]
|
|
19
|
+
};
|
|
20
|
+
if (existingOptions) {
|
|
21
|
+
const existingFromDescendent = (0, is_descendent_1.isDescendent)(plugin, existingOptions.plugin);
|
|
22
|
+
// plugins can only override options from their descendents, otherwise it's a conflict
|
|
23
|
+
// return a conflict either listing these options and the sibling's,
|
|
24
|
+
// or merging in previously-generated options
|
|
25
|
+
if (!existingFromDescendent) {
|
|
26
|
+
const conflicting = (0, conflict_1.isConflict)(existingOptions) ? existingOptions.conflicting : [existingOptions];
|
|
27
|
+
const conflict = {
|
|
28
|
+
plugin,
|
|
29
|
+
conflicting: conflicting.concat(pluginOptions)
|
|
30
|
+
};
|
|
31
|
+
config.pluginOptions[pluginId] = conflict;
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
// if we're here, any existing options are from a child plugin,
|
|
35
|
+
// so merge in overrides from the parent
|
|
36
|
+
config.pluginOptions[pluginId] = { ...existingOptions, ...pluginOptions };
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
// this options key might not have been set yet, in which case use the new one
|
|
41
|
+
config.pluginOptions[pluginId] = pluginOptions;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
exports.mergePluginOptions = mergePluginOptions;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"merge-task-options.d.ts","sourceRoot":"","sources":["../../src/plugin/merge-task-options.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAkB,MAAM,yBAAyB,CAAA;AACrE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AAOjE,eAAO,MAAM,gBAAgB,WAAY,kBAAkB,UAAU,MAAM,SAqC1E,CAAA"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.mergeTaskOptions = void 0;
|
|
4
|
+
const conflict_1 = require("@dotcom-tool-kit/conflict");
|
|
5
|
+
const is_descendent_1 = require("./is-descendent");
|
|
6
|
+
// merge options from this plugin's config with any options we've collected already
|
|
7
|
+
// TODO this is almost the exact same code as for command tasks, refactor
|
|
8
|
+
const mergeTaskOptions = (config, plugin) => {
|
|
9
|
+
if (plugin.rcFile) {
|
|
10
|
+
for (const [taskId, configOptions] of Object.entries(plugin.rcFile.options.tasks)) {
|
|
11
|
+
const existingOptions = config.taskOptions[taskId];
|
|
12
|
+
const taskOptions = {
|
|
13
|
+
options: configOptions,
|
|
14
|
+
plugin,
|
|
15
|
+
task: taskId
|
|
16
|
+
};
|
|
17
|
+
if (existingOptions) {
|
|
18
|
+
const existingFromDescendent = (0, is_descendent_1.isDescendent)(plugin, existingOptions.plugin);
|
|
19
|
+
// plugins can only override options from their descendents, otherwise it's a conflict
|
|
20
|
+
// return a conflict either listing these options and the sibling's,
|
|
21
|
+
// or merging in previously-generated options
|
|
22
|
+
if (!existingFromDescendent) {
|
|
23
|
+
const conflicting = (0, conflict_1.isConflict)(existingOptions) ? existingOptions.conflicting : [existingOptions];
|
|
24
|
+
const conflict = {
|
|
25
|
+
plugin,
|
|
26
|
+
conflicting: conflicting.concat(taskOptions)
|
|
27
|
+
};
|
|
28
|
+
config.taskOptions[taskId] = conflict;
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
// if we're here, any existing options are from a child plugin,
|
|
32
|
+
// so merge in overrides from the parent
|
|
33
|
+
config.taskOptions[taskId] = { ...existingOptions, ...taskOptions };
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
// this options key might not have been set yet, in which case use the new one
|
|
38
|
+
config.taskOptions[taskId] = taskOptions;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
exports.mergeTaskOptions = mergeTaskOptions;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"merge-tasks.d.ts","sourceRoot":"","sources":["../../src/plugin/merge-tasks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAc,MAAM,EAAE,MAAM,yBAAyB,CAAA;AACjE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AAIjE,eAAO,MAAM,UAAU,WAAY,kBAAkB,UAAU,MAAM,SAqBpE,CAAA"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.mergeTasks = void 0;
|
|
4
|
+
const conflict_1 = require("@dotcom-tool-kit/conflict");
|
|
5
|
+
// add plugin tasks to our task registry, handling any conflicts
|
|
6
|
+
const mergeTasks = (config, plugin) => {
|
|
7
|
+
if (plugin.rcFile) {
|
|
8
|
+
for (const [taskName, modulePath] of Object.entries(plugin.rcFile.tasks || {})) {
|
|
9
|
+
const existingTaskId = config.tasks[taskName];
|
|
10
|
+
const entryPoint = {
|
|
11
|
+
plugin,
|
|
12
|
+
modulePath
|
|
13
|
+
};
|
|
14
|
+
if (existingTaskId) {
|
|
15
|
+
const conflicting = (0, conflict_1.isConflict)(existingTaskId) ? existingTaskId.conflicting : [existingTaskId];
|
|
16
|
+
config.tasks[taskName] = {
|
|
17
|
+
plugin,
|
|
18
|
+
conflicting: conflicting.concat(entryPoint)
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
config.tasks[taskName] = entryPoint;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
exports.mergeTasks = mergeTasks;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { ValidPluginsConfig } from '@dotcom-tool-kit/config';
|
|
2
|
+
import { type Plugin } from '@dotcom-tool-kit/plugin';
|
|
3
|
+
import type { Logger } from 'winston';
|
|
4
|
+
import { InvalidOption } from '../messages';
|
|
5
|
+
export declare const validatePluginOptions: (logger: Logger, config: ValidPluginsConfig) => InvalidOption[];
|
|
6
|
+
export declare const substituteOptionTags: (plugin: Plugin, config: ValidPluginsConfig) => void;
|
|
7
|
+
//# sourceMappingURL=options.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"options.d.ts","sourceRoot":"","sources":["../../src/plugin/options.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AAE5D,OAAO,EAA4B,KAAK,MAAM,EAAE,MAAM,yBAAyB,CAAA;AAI/E,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AAKrC,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAE3C,eAAO,MAAM,qBAAqB,WAAY,MAAM,UAAU,kBAAkB,KAAG,aAAa,EAoD/F,CAAA;AAED,eAAO,MAAM,oBAAoB,WAAY,MAAM,UAAU,kBAAkB,KAAG,IAgHjF,CAAA"}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.substituteOptionTags = exports.validatePluginOptions = void 0;
|
|
4
|
+
const conflict_1 = require("@dotcom-tool-kit/conflict");
|
|
5
|
+
const schemas_1 = require("@dotcom-tool-kit/schemas");
|
|
6
|
+
const validated_1 = require("@dotcom-tool-kit/validated");
|
|
7
|
+
const zod_1 = require("zod");
|
|
8
|
+
const logger_1 = require("@dotcom-tool-kit/logger");
|
|
9
|
+
const rc_file_1 = require("../rc-file");
|
|
10
|
+
const validatePluginOptions = (logger, config) => {
|
|
11
|
+
const invalidOptions = [];
|
|
12
|
+
for (const [id, plugin] of Object.entries(config.plugins)) {
|
|
13
|
+
const pluginId = id;
|
|
14
|
+
const pluginOptions = config.pluginOptions[pluginId];
|
|
15
|
+
if (pluginOptions && (0, conflict_1.isConflict)(pluginOptions)) {
|
|
16
|
+
continue;
|
|
17
|
+
}
|
|
18
|
+
const pluginSchema = schemas_1.PluginSchemas[pluginId];
|
|
19
|
+
if (!pluginSchema) {
|
|
20
|
+
logger.silly(`skipping validation of ${pluginId} plugin as no schema can be found`);
|
|
21
|
+
// TODO:KB:20240412 remove legacyPluginOptions in a future major version
|
|
22
|
+
if (pluginOptions && pluginId in schemas_1.legacyPluginOptions) {
|
|
23
|
+
const movedToTask = schemas_1.legacyPluginOptions[pluginId];
|
|
24
|
+
invalidOptions.push([
|
|
25
|
+
id,
|
|
26
|
+
new zod_1.ZodError([
|
|
27
|
+
{
|
|
28
|
+
message: `options for ${logger_1.styles.plugin(id)} have moved to the ${logger_1.styles.task(movedToTask)} task`,
|
|
29
|
+
code: zod_1.ZodIssueCode.custom,
|
|
30
|
+
path: []
|
|
31
|
+
}
|
|
32
|
+
])
|
|
33
|
+
]);
|
|
34
|
+
}
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
const result = pluginSchema.safeParse(pluginOptions?.options ?? {});
|
|
38
|
+
if (result.success) {
|
|
39
|
+
// Set up options entry for plugins that don't have options specified
|
|
40
|
+
// explicitly. They could still have default options that are set by zod.
|
|
41
|
+
if (!pluginOptions) {
|
|
42
|
+
config.pluginOptions[pluginId] = {
|
|
43
|
+
options: result.data,
|
|
44
|
+
plugin: config.plugins['app root'],
|
|
45
|
+
forPlugin: plugin
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
pluginOptions.options = result.data;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
invalidOptions.push([id, result.error]);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return invalidOptions;
|
|
57
|
+
};
|
|
58
|
+
exports.validatePluginOptions = validatePluginOptions;
|
|
59
|
+
const substituteOptionTags = (plugin, config) => {
|
|
60
|
+
// foo.bar gets the 'bar' option set for the 'foo' plugin
|
|
61
|
+
const resolveOptionPath = (optionPath) => {
|
|
62
|
+
const [pluginName, optionName] = optionPath.split('.', 2);
|
|
63
|
+
return config.pluginOptions[pluginName]?.options[optionName];
|
|
64
|
+
};
|
|
65
|
+
// throw an error if there are tags in plugin option fields to avoid circular
|
|
66
|
+
// references
|
|
67
|
+
const validateTagPath = (path) => {
|
|
68
|
+
if (path[0] === 'options' && path[1] === 'plugins') {
|
|
69
|
+
return `YAML tag referencing options used at path '${path.join('.')}'`;
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
// recursively walk through the parsed config, searching for the tag
|
|
73
|
+
// identifiers we've inserted during parsing, and substitute them for
|
|
74
|
+
// resolved option values
|
|
75
|
+
const deeplySubstitute = (node, path) => {
|
|
76
|
+
if (Array.isArray(node)) {
|
|
77
|
+
return (0, validated_1.reduceValidated)(node.map((item, i) => deeplySubstitute(item, [...path, i])));
|
|
78
|
+
}
|
|
79
|
+
else if (node && typeof node === 'object') {
|
|
80
|
+
const entries = Object.entries(node);
|
|
81
|
+
const substituted = [];
|
|
82
|
+
for (const entry of entries) {
|
|
83
|
+
const subbedEntry = (0, validated_1.reduceValidated)(
|
|
84
|
+
// allow both keys and (string) values to be substituted by options
|
|
85
|
+
entry.map((val) => {
|
|
86
|
+
if (typeof val === 'string' && val.startsWith(rc_file_1.toolKitOptionIdent)) {
|
|
87
|
+
// check the tag path each time so that we can have a separate
|
|
88
|
+
// error for each incorrect use of the tag
|
|
89
|
+
const validationError = validateTagPath([...path, entry[0]]);
|
|
90
|
+
if (validationError) {
|
|
91
|
+
return (0, validated_1.invalid)([validationError]);
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
// the option path is concatenated after the !toolkit/option
|
|
95
|
+
// identifier
|
|
96
|
+
const optionPath = val.slice(rc_file_1.toolKitOptionIdent.length);
|
|
97
|
+
const resolvedOption = resolveOptionPath(optionPath);
|
|
98
|
+
if (typeof resolvedOption === 'string') {
|
|
99
|
+
return (0, validated_1.valid)(resolvedOption);
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
return (0, validated_1.invalid)([
|
|
103
|
+
`Option '${optionPath}' referenced at path '${path.join('.')}' does not resolve to a string (resolved to ${resolvedOption})`
|
|
104
|
+
]);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
return (0, validated_1.valid)(val);
|
|
110
|
+
}
|
|
111
|
+
}));
|
|
112
|
+
if (!subbedEntry.valid) {
|
|
113
|
+
/* eslint-disable-next-line @typescript-eslint/no-explicit-any --
|
|
114
|
+
* Invalid objects don't need to match the inner type
|
|
115
|
+
**/
|
|
116
|
+
substituted.push(subbedEntry);
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
119
|
+
const [key, value] = subbedEntry.value;
|
|
120
|
+
if (key.startsWith(rc_file_1.toolKitIfDefinedIdent)) {
|
|
121
|
+
const validationError = validateTagPath(path);
|
|
122
|
+
if (validationError) {
|
|
123
|
+
substituted.push((0, validated_1.invalid)([validationError]));
|
|
124
|
+
}
|
|
125
|
+
// the option path is concatenated after the !toolkit/if-defined
|
|
126
|
+
// identifier
|
|
127
|
+
const optionPath = key.slice(rc_file_1.toolKitIfDefinedIdent.length);
|
|
128
|
+
const optionValue = resolveOptionPath(optionPath);
|
|
129
|
+
// keep walking the path if we've found an error here so we can
|
|
130
|
+
// gather even more errors to show the user. else skip traversal if
|
|
131
|
+
// we aren't going to include the node
|
|
132
|
+
if (optionValue || validationError) {
|
|
133
|
+
const subbedValues = deeplySubstitute(value, path);
|
|
134
|
+
if (subbedValues.valid) {
|
|
135
|
+
substituted.push(...Object.entries(subbedValues.value).map((v) => (0, validated_1.valid)(v)));
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
/* eslint-disable-next-line @typescript-eslint/no-explicit-any --
|
|
139
|
+
* Invalid objects don't need to match the inner type
|
|
140
|
+
**/
|
|
141
|
+
substituted.push(subbedValues);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
substituted.push(deeplySubstitute(value, [...path, key]).map((subbedValue) => [key, subbedValue]));
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
return (0, validated_1.reduceValidated)(substituted).map(Object.fromEntries);
|
|
150
|
+
}
|
|
151
|
+
else {
|
|
152
|
+
return (0, validated_1.valid)(node);
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
// avoid running substitution over a config repeatedly – all substitutions
|
|
156
|
+
// will have been made in the first pass
|
|
157
|
+
if (config.resolutionTrackers.substitutedPlugins.has(plugin.id)) {
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
if (plugin.children) {
|
|
161
|
+
for (const child of plugin.children) {
|
|
162
|
+
(0, exports.substituteOptionTags)(child, config);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
if (plugin.rcFile) {
|
|
166
|
+
plugin.rcFile = deeplySubstitute(plugin.rcFile, []).unwrap('cannot reference plugin options when specifying options');
|
|
167
|
+
}
|
|
168
|
+
config.resolutionTrackers.substitutedPlugins.add(plugin.id);
|
|
169
|
+
};
|
|
170
|
+
exports.substituteOptionTags = substituteOptionTags;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { Logger } from 'winston';
|
|
2
|
+
import type { HookClass, HookInstallation } from '@dotcom-tool-kit/base';
|
|
3
|
+
import type { Plugin } from '@dotcom-tool-kit/plugin';
|
|
4
|
+
import type { ValidConfig } from '@dotcom-tool-kit/config';
|
|
5
|
+
import { Conflict } from '@dotcom-tool-kit/conflict';
|
|
6
|
+
export declare function reducePluginHookInstallations(logger: Logger, config: ValidConfig, hookClasses: Record<string, HookClass>, plugin: Plugin): Promise<(HookInstallation | Conflict<HookInstallation>)[]>;
|
|
7
|
+
//# sourceMappingURL=reduce-installations.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reduce-installations.d.ts","sourceRoot":"","sources":["../../src/plugin/reduce-installations.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AACrC,OAAO,KAAK,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AACxE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAA;AACrD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAA;AAE1D,OAAO,EAAE,QAAQ,EAAc,MAAM,2BAA2B,CAAA;AAgChE,wBAAsB,6BAA6B,CACjD,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,WAAW,EACnB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,EACtC,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,CAAC,gBAAgB,GAAG,QAAQ,CAAC,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAwC5D"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.reducePluginHookInstallations = void 0;
|
|
4
|
+
const schemas_1 = require("@dotcom-tool-kit/schemas");
|
|
5
|
+
const conflict_1 = require("@dotcom-tool-kit/conflict");
|
|
6
|
+
const lodash_1 = require("lodash");
|
|
7
|
+
const extractForHook = (installation) => (0, conflict_1.isConflict)(installation) ? installation.conflicting[0].forHook : installation.forHook;
|
|
8
|
+
// this function recursively collects all the hook installation requests from all plugins,
|
|
9
|
+
// and merges them into a single, flat array of HookInstallation objects and/or Conflicts.
|
|
10
|
+
//
|
|
11
|
+
// it works depth-first (i.e. recurses into child plugins first), and considers how to
|
|
12
|
+
// merge options or create conflicts in two stages: 1) when considering all installations
|
|
13
|
+
// from child plugins, and 2) when considering how a parent plugin would override its
|
|
14
|
+
// children. these steps are separate as a particular parent might not provide an override
|
|
15
|
+
// for all its children, and different hooks could expect different ways of resolving
|
|
16
|
+
// conflicts.
|
|
17
|
+
//
|
|
18
|
+
// the actual logic for this is delegated to static methods on Hook classes,
|
|
19
|
+
// `Hook.mergeChildInstallations` and `Hook.overrideChildInstallations`, so separate hooks
|
|
20
|
+
// can provide different logic for these steps.
|
|
21
|
+
//
|
|
22
|
+
// the default logic in the base Hook class is to always consider multiple installations
|
|
23
|
+
// from child plugins as a conflict, and always consider a installation in a parent as
|
|
24
|
+
// completely replacing any installations from children.
|
|
25
|
+
//
|
|
26
|
+
// for example, for a plugin `p` that depends on children `a`, `b`, and `c` that all provide
|
|
27
|
+
// configuration for the `PackageJson` hook, this function will:
|
|
28
|
+
// - do all this logic for `a`, `b`, and `c`
|
|
29
|
+
// - call `Hook.mergeChildInstallations` with the appropriate concrete Hook class, and
|
|
30
|
+
// the resulting installations and/or conflicts from `a`, `b`, and `c`
|
|
31
|
+
// - call `Hook.overrideChildInstallations` with the appropriate concrete Hook class, and
|
|
32
|
+
// the resulting installations and/or conflicts from `Hook.mergeChildInstallations` and `p`
|
|
33
|
+
async function reducePluginHookInstallations(logger, config, hookClasses, plugin) {
|
|
34
|
+
if (!plugin.rcFile || config.resolutionTrackers.reducedInstallationPlugins.has(plugin.id)) {
|
|
35
|
+
return [];
|
|
36
|
+
}
|
|
37
|
+
config.resolutionTrackers.reducedInstallationPlugins.add(plugin.id);
|
|
38
|
+
const rawChildInstallations = await Promise.all((plugin.children ?? []).map((child) => reducePluginHookInstallations(logger, config, hookClasses, child))).then((installations) => installations.flat());
|
|
39
|
+
const childInstallations = Object.entries((0, lodash_1.groupBy)(rawChildInstallations, extractForHook)).flatMap(([forHook, installations]) => {
|
|
40
|
+
const hookClass = hookClasses[forHook];
|
|
41
|
+
return hookClass.mergeChildInstallations(plugin, installations);
|
|
42
|
+
});
|
|
43
|
+
if (plugin.rcFile.options.hooks.length === 0) {
|
|
44
|
+
return childInstallations;
|
|
45
|
+
}
|
|
46
|
+
return plugin.rcFile.options.hooks.flatMap((hookEntry) => Object.entries(hookEntry).flatMap(([id, configHookOptions]) => {
|
|
47
|
+
const hookClass = hookClasses[id];
|
|
48
|
+
const parsedOptions = schemas_1.HookSchemas[id].parse(configHookOptions);
|
|
49
|
+
const installation = {
|
|
50
|
+
options: parsedOptions,
|
|
51
|
+
plugin,
|
|
52
|
+
forHook: id,
|
|
53
|
+
hookConstructor: hookClass
|
|
54
|
+
};
|
|
55
|
+
const childInstallationsForHook = childInstallations.filter((childInstallation) => id === extractForHook(childInstallation));
|
|
56
|
+
return hookClass.overrideChildInstallations(plugin, installation, childInstallationsForHook);
|
|
57
|
+
}));
|
|
58
|
+
}
|
|
59
|
+
exports.reducePluginHookInstallations = reducePluginHookInstallations;
|
package/lib/plugin.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { Plugin
|
|
1
|
+
import { type Plugin } from '@dotcom-tool-kit/plugin';
|
|
2
|
+
import type { RawConfig, ValidPluginsConfig } from '@dotcom-tool-kit/config';
|
|
3
|
+
import { Validated } from '@dotcom-tool-kit/validated';
|
|
2
4
|
import type { Logger } from 'winston';
|
|
3
|
-
import { RawConfig, ValidPluginsConfig } from './config';
|
|
4
|
-
export declare function validatePlugin(plugin: unknown): Validated<PluginModule>;
|
|
5
5
|
export declare function loadPlugin(id: string, config: RawConfig, logger: Logger, parent?: Plugin): Promise<Validated<Plugin>>;
|
|
6
|
+
export declare function resolvePluginOptions(plugin: Plugin, config: ValidPluginsConfig): void;
|
|
6
7
|
export declare function resolvePlugin(plugin: Plugin, config: ValidPluginsConfig, logger: Logger): void;
|
|
7
8
|
//# 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":"AACA,OAAO,
|
|
1
|
+
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AACA,OAAO,EAA2B,KAAK,MAAM,EAAE,MAAM,yBAAyB,CAAA;AAC9E,OAAO,KAAK,EAAE,SAAS,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AAC5E,OAAO,EAAmC,SAAS,EAAE,MAAM,4BAA4B,CAAA;AAEvF,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AAUrC,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,CAmD5B;AAED,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,kBAAkB,GAAG,IAAI,CAiBrF;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,kBAAkB,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAqB9F"}
|