dotcom-tool-kit 3.5.0 → 4.0.0-beta.0
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 +92 -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
package/bin/run
CHANGED
|
@@ -1,22 +1,32 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
+
/* eslint-disable @typescript-eslint/no-var-requires --
|
|
4
|
+
* this is raw CJS so the lint doesn't apply
|
|
5
|
+
*/
|
|
6
|
+
|
|
3
7
|
const argv = require('minimist')(process.argv.slice(2), {
|
|
4
8
|
boolean: ['help', 'install', 'listPlugins'],
|
|
5
9
|
'--': true
|
|
6
10
|
})
|
|
7
11
|
|
|
8
|
-
const { runTasks, showHelp, installHooks, listPlugins } = require('../lib')
|
|
9
12
|
const { rootLogger, styles } = require('@dotcom-tool-kit/logger')
|
|
10
13
|
|
|
11
14
|
async function main() {
|
|
12
15
|
try {
|
|
13
16
|
if (argv.install) {
|
|
17
|
+
const installHooks = require('../lib/install').default
|
|
14
18
|
await installHooks(rootLogger)
|
|
15
19
|
} else if (argv.listPlugins) {
|
|
20
|
+
const { listPlugins } = require('../lib')
|
|
16
21
|
await listPlugins(rootLogger)
|
|
22
|
+
} else if (argv.printConfig) {
|
|
23
|
+
const { printConfig } = require('../lib')
|
|
24
|
+
await printConfig(rootLogger)
|
|
17
25
|
} else if (argv.help || argv._.length === 0) {
|
|
26
|
+
const showHelp = require('../lib/help').default
|
|
18
27
|
await showHelp(rootLogger, argv._)
|
|
19
28
|
} else {
|
|
29
|
+
const { runTasks } = require('../lib')
|
|
20
30
|
if (argv['--'].length > 0) {
|
|
21
31
|
// The `--` in a command such as `dotcom-tool-kit test:staged --`
|
|
22
32
|
// delineates between hooks and file patterns. For example, when the
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { ValidConfig } from '@dotcom-tool-kit/config';
|
|
2
|
+
import { Logger } from 'winston';
|
|
3
|
+
export declare function fileHash(path: string): Promise<string>;
|
|
4
|
+
export declare function updateHashes(config: ValidConfig): Promise<void>;
|
|
5
|
+
export declare function hasConfigChanged(logger: Logger, config: ValidConfig): Promise<boolean>;
|
|
6
|
+
//# sourceMappingURL=hash.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hash.d.ts","sourceRoot":"","sources":["../../src/config/hash.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAA;AAIrD,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AAEhC,wBAAsB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAY5D;AAED,wBAAsB,YAAY,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAOrE;AAED,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC,CAiB5F"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.hasConfigChanged = exports.updateHashes = exports.fileHash = void 0;
|
|
4
|
+
const state_1 = require("@dotcom-tool-kit/state");
|
|
5
|
+
const node_crypto_1 = require("node:crypto");
|
|
6
|
+
const promises_1 = require("node:fs/promises");
|
|
7
|
+
async function fileHash(path) {
|
|
8
|
+
const hashFunc = (0, node_crypto_1.createHash)('sha512');
|
|
9
|
+
try {
|
|
10
|
+
hashFunc.update(await (0, promises_1.readFile)(path));
|
|
11
|
+
return hashFunc.digest('base64');
|
|
12
|
+
}
|
|
13
|
+
catch (error) {
|
|
14
|
+
if (error?.code === 'ENOENT') {
|
|
15
|
+
return 'n/a';
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
throw error;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
exports.fileHash = fileHash;
|
|
23
|
+
async function updateHashes(config) {
|
|
24
|
+
const hashes = Object.fromEntries(await Promise.all(['.toolkitrc.yml', ...config.hookManagedFiles].map(async (path) => [path, await fileHash(path)])));
|
|
25
|
+
(0, state_1.writeState)('install', hashes);
|
|
26
|
+
}
|
|
27
|
+
exports.updateHashes = updateHashes;
|
|
28
|
+
async function hasConfigChanged(logger, config) {
|
|
29
|
+
const hashes = (0, state_1.readState)('install');
|
|
30
|
+
if (!hashes) {
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
33
|
+
for (const path of ['.toolkitrc.yml', ...config.hookManagedFiles]) {
|
|
34
|
+
const newHash = await fileHash(path);
|
|
35
|
+
const prevHash = hashes[path];
|
|
36
|
+
if (newHash !== prevHash) {
|
|
37
|
+
logger.debug(`hash for path ${path} has changed, running hook checks`);
|
|
38
|
+
return true;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
exports.hasConfigChanged = hasConfigChanged;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { RawConfig, ValidPluginsConfig } from '@dotcom-tool-kit/config';
|
|
2
|
+
import { Validated } from '@dotcom-tool-kit/validated';
|
|
3
|
+
export declare function validatePlugins(config: RawConfig): Validated<ValidPluginsConfig>;
|
|
4
|
+
//# sourceMappingURL=validate-plugins.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate-plugins.d.ts","sourceRoot":"","sources":["../../src/config/validate-plugins.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AAC5E,OAAO,EAAE,SAAS,EAAmB,MAAM,4BAA4B,CAAA;AAEvE,wBAAgB,eAAe,CAAC,MAAM,EAAE,SAAS,GAAG,SAAS,CAAC,kBAAkB,CAAC,CAKhF"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.validatePlugins = void 0;
|
|
4
|
+
const validated_1 = require("@dotcom-tool-kit/validated");
|
|
5
|
+
function validatePlugins(config) {
|
|
6
|
+
const validatedPlugins = (0, validated_1.reduceValidated)(Object.entries(config.plugins).map(([id, plugin]) => plugin.map((p) => [id, p])));
|
|
7
|
+
return validatedPlugins.map((plugins) => ({ ...config, plugins: Object.fromEntries(plugins) }));
|
|
8
|
+
}
|
|
9
|
+
exports.validatePlugins = validatePlugins;
|
package/lib/config.d.ts
CHANGED
|
@@ -1,59 +1,7 @@
|
|
|
1
1
|
import type { Logger } from 'winston';
|
|
2
|
-
import
|
|
3
|
-
import { Conflict } from './conflict';
|
|
4
|
-
import { TaskClass, Hook, Plugin, Validated } from '@dotcom-tool-kit/types';
|
|
5
|
-
import { Options as SchemaOptions } from '@dotcom-tool-kit/types/lib/schema';
|
|
6
|
-
export interface PluginOptions {
|
|
7
|
-
options: Record<string, unknown>;
|
|
8
|
-
plugin: Plugin;
|
|
9
|
-
forPlugin: Plugin;
|
|
10
|
-
}
|
|
11
|
-
export interface RawConfig {
|
|
12
|
-
root: string;
|
|
13
|
-
plugins: {
|
|
14
|
-
[id: string]: Validated<Plugin>;
|
|
15
|
-
};
|
|
16
|
-
resolvedPlugins: Set<Plugin>;
|
|
17
|
-
tasks: {
|
|
18
|
-
[id: string]: TaskClass | Conflict<TaskClass>;
|
|
19
|
-
};
|
|
20
|
-
hookTasks: {
|
|
21
|
-
[id: string]: HookTask | Conflict<HookTask>;
|
|
22
|
-
};
|
|
23
|
-
options: {
|
|
24
|
-
[id: string]: PluginOptions | Conflict<PluginOptions> | undefined;
|
|
25
|
-
};
|
|
26
|
-
hooks: {
|
|
27
|
-
[id: string]: Hook<unknown> | Conflict<Hook<unknown>>;
|
|
28
|
-
};
|
|
29
|
-
}
|
|
30
|
-
export type ValidPluginsConfig = Omit<RawConfig, 'plugins'> & {
|
|
31
|
-
plugins: {
|
|
32
|
-
[id: string]: Plugin;
|
|
33
|
-
};
|
|
34
|
-
};
|
|
35
|
-
export type ValidPluginOptions<Id extends keyof SchemaOptions> = Omit<PluginOptions, 'options'> & {
|
|
36
|
-
options: SchemaOptions[Id];
|
|
37
|
-
};
|
|
38
|
-
export type ValidOptions = {
|
|
39
|
-
[Id in keyof SchemaOptions]: ValidPluginOptions<Id>;
|
|
40
|
-
};
|
|
41
|
-
export type ValidConfig = Omit<ValidPluginsConfig, 'tasks' | 'hookTasks' | 'options' | 'hooks'> & {
|
|
42
|
-
tasks: {
|
|
43
|
-
[id: string]: TaskClass;
|
|
44
|
-
};
|
|
45
|
-
hookTasks: {
|
|
46
|
-
[id: string]: HookTask;
|
|
47
|
-
};
|
|
48
|
-
options: ValidOptions;
|
|
49
|
-
hooks: {
|
|
50
|
-
[id: string]: Hook<unknown>;
|
|
51
|
-
};
|
|
52
|
-
};
|
|
2
|
+
import { RawConfig, ValidConfig, ValidPluginsConfig } from '@dotcom-tool-kit/config';
|
|
53
3
|
export declare const createConfig: () => RawConfig;
|
|
54
|
-
export declare function validateConfig(config: ValidPluginsConfig
|
|
55
|
-
export declare function validatePlugins(config: RawConfig): Validated<ValidPluginsConfig>;
|
|
56
|
-
export declare function checkInstall(config: ValidConfig): Promise<void>;
|
|
4
|
+
export declare function validateConfig(config: ValidPluginsConfig): ValidConfig;
|
|
57
5
|
export declare function loadConfig(logger: Logger, options?: {
|
|
58
6
|
validate?: true;
|
|
59
7
|
}): Promise<ValidConfig>;
|
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;
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AAUrC,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AAiBpF,eAAO,MAAM,YAAY,QAAO,SAgB9B,CAAA;AAEF,wBAAgB,cAAc,CAAC,MAAM,EAAE,kBAAkB,GAAG,WAAW,CAiGtE;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,124 +1,90 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.loadConfig = exports.
|
|
3
|
+
exports.loadConfig = exports.validateConfig = exports.createConfig = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const path_1 = tslib_1.__importDefault(require("path"));
|
|
6
6
|
const plugin_1 = require("./plugin");
|
|
7
|
-
const conflict_1 = require("
|
|
7
|
+
const conflict_1 = require("@dotcom-tool-kit/conflict");
|
|
8
8
|
const error_1 = require("@dotcom-tool-kit/error");
|
|
9
|
-
const types_1 = require("@dotcom-tool-kit/types");
|
|
10
|
-
const schema_1 = require("@dotcom-tool-kit/types/lib/schema");
|
|
11
9
|
const messages_1 = require("./messages");
|
|
10
|
+
const validate_plugins_1 = require("./config/validate-plugins");
|
|
11
|
+
const options_1 = require("./plugin/options");
|
|
12
12
|
const coreRoot = path_1.default.resolve(__dirname, '../');
|
|
13
13
|
const createConfig = () => ({
|
|
14
14
|
root: coreRoot,
|
|
15
15
|
plugins: {},
|
|
16
|
-
|
|
16
|
+
resolutionTrackers: {
|
|
17
|
+
resolvedPluginOptions: new Set(),
|
|
18
|
+
substitutedPlugins: new Set(),
|
|
19
|
+
resolvedPlugins: new Set(),
|
|
20
|
+
reducedInstallationPlugins: new Set()
|
|
21
|
+
},
|
|
17
22
|
tasks: {},
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
23
|
+
commandTasks: {},
|
|
24
|
+
pluginOptions: {},
|
|
25
|
+
taskOptions: {},
|
|
26
|
+
hooks: {},
|
|
27
|
+
inits: [],
|
|
28
|
+
hookManagedFiles: new Set()
|
|
21
29
|
});
|
|
22
30
|
exports.createConfig = createConfig;
|
|
23
|
-
|
|
24
|
-
const results = await Promise.all(items.map(async (item) => ({ item, keep: await predicate(item) })));
|
|
25
|
-
return results.filter(({ keep }) => keep).map(({ item }) => item);
|
|
26
|
-
}
|
|
27
|
-
function validateConfig(config, logger) {
|
|
31
|
+
function validateConfig(config) {
|
|
28
32
|
const validConfig = config;
|
|
29
|
-
const
|
|
30
|
-
const hookConflicts = (0, conflict_1.
|
|
31
|
-
const taskConflicts = (0, conflict_1.
|
|
32
|
-
const
|
|
33
|
-
const
|
|
33
|
+
const commandTaskConflicts = (0, conflict_1.findConflicts)(Object.values(config.commandTasks));
|
|
34
|
+
const hookConflicts = (0, conflict_1.findConflictingEntries)(config.hooks);
|
|
35
|
+
const taskConflicts = (0, conflict_1.findConflictingEntries)(config.tasks);
|
|
36
|
+
const pluginOptionConflicts = (0, conflict_1.findConflicts)(Object.values(config.pluginOptions));
|
|
37
|
+
const taskOptionConflicts = (0, conflict_1.findConflicts)(Object.values(config.taskOptions));
|
|
38
|
+
const definedCommandTaskConflicts = commandTaskConflicts.filter((conflict) => {
|
|
34
39
|
return conflict.conflicting[0].id in config.hooks;
|
|
35
40
|
});
|
|
36
41
|
let shouldThrow = false;
|
|
37
|
-
const error = new error_1.ToolKitConflictError('There are problems with your Tool Kit configuration.',
|
|
38
|
-
|
|
39
|
-
conflictingTasks: conflict.conflicting.flatMap((
|
|
42
|
+
const error = new error_1.ToolKitConflictError('There are problems with your Tool Kit configuration.', commandTaskConflicts.map((conflict) => ({
|
|
43
|
+
command: conflict.conflicting[0].id,
|
|
44
|
+
conflictingTasks: conflict.conflicting.flatMap((command) => command.tasks.map((task) => ({ task: task.task, plugin: command.plugin.id })))
|
|
40
45
|
})));
|
|
41
46
|
error.details = '';
|
|
42
47
|
if (hookConflicts.length > 0 ||
|
|
43
|
-
|
|
48
|
+
definedCommandTaskConflicts.length > 0 ||
|
|
44
49
|
taskConflicts.length > 0 ||
|
|
45
|
-
|
|
50
|
+
pluginOptionConflicts.length > 0 ||
|
|
51
|
+
taskOptionConflicts.length > 0) {
|
|
46
52
|
shouldThrow = true;
|
|
47
53
|
if (hookConflicts.length) {
|
|
48
54
|
error.details += (0, messages_1.formatHookConflicts)(hookConflicts);
|
|
49
55
|
}
|
|
50
|
-
if (
|
|
51
|
-
error.details += (0, messages_1.
|
|
56
|
+
if (definedCommandTaskConflicts.length) {
|
|
57
|
+
error.details += (0, messages_1.formatCommandTaskConflicts)(definedCommandTaskConflicts);
|
|
52
58
|
}
|
|
53
59
|
if (taskConflicts.length) {
|
|
54
60
|
error.details += (0, messages_1.formatTaskConflicts)(taskConflicts);
|
|
55
61
|
}
|
|
56
|
-
if (
|
|
57
|
-
error.details += (0, messages_1.
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
const configuredHookTasks = (0, conflict_1.withoutConflicts)(Object.values(config.hookTasks));
|
|
61
|
-
const definedHookIds = new Set(Object.keys(config.hooks));
|
|
62
|
-
const undefinedHookTasks = configuredHookTasks.filter((hookTask) => {
|
|
63
|
-
// we only care about undefined hooks that were configured by the app, not default config from plugins
|
|
64
|
-
const fromApp = hookTask.plugin.root === process.cwd();
|
|
65
|
-
const hookDefined = definedHookIds.has(hookTask.id);
|
|
66
|
-
return fromApp && !hookDefined;
|
|
67
|
-
});
|
|
68
|
-
if (undefinedHookTasks.length > 0) {
|
|
69
|
-
shouldThrow = true;
|
|
70
|
-
error.details += (0, messages_1.formatUndefinedHookTasks)(undefinedHookTasks, Array.from(definedHookIds));
|
|
71
|
-
}
|
|
72
|
-
const invalidOptions = [];
|
|
73
|
-
for (const [id, plugin] of Object.entries(config.plugins)) {
|
|
74
|
-
const pluginId = id;
|
|
75
|
-
const pluginOptions = config.options[pluginId];
|
|
76
|
-
if (pluginOptions && (0, conflict_1.isConflict)(pluginOptions)) {
|
|
77
|
-
continue;
|
|
78
|
-
}
|
|
79
|
-
const pluginSchema = schema_1.Schemas[pluginId];
|
|
80
|
-
if (!pluginSchema) {
|
|
81
|
-
logger.silly(`skipping validation of ${pluginId} plugin as no schema can be found`);
|
|
82
|
-
continue;
|
|
83
|
-
}
|
|
84
|
-
const result = pluginSchema.safeParse(pluginOptions?.options ?? {});
|
|
85
|
-
if (result.success) {
|
|
86
|
-
// Set up options entry for plugins that don't have options specified
|
|
87
|
-
// explicitly. They could still have default options that are set by zod.
|
|
88
|
-
if (!pluginOptions) {
|
|
89
|
-
// TypeScript struggles with this type as it sees one side as
|
|
90
|
-
// `Foo<a | b | c>` and the other as `Foo<a> | Foo<b> | Foo<c>` for
|
|
91
|
-
// some reason (something to do with the record indexing) and it can't
|
|
92
|
-
// unify them. But they are equivalent so let's force it with a cast.
|
|
93
|
-
config.options[pluginId] = {
|
|
94
|
-
options: result.data,
|
|
95
|
-
plugin: config.plugins['app root'],
|
|
96
|
-
forPlugin: plugin
|
|
97
|
-
}; // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
98
|
-
}
|
|
99
|
-
else {
|
|
100
|
-
pluginOptions.options = result.data;
|
|
101
|
-
}
|
|
62
|
+
if (pluginOptionConflicts.length) {
|
|
63
|
+
error.details += (0, messages_1.formatPluginOptionConflicts)(pluginOptionConflicts);
|
|
102
64
|
}
|
|
103
|
-
|
|
104
|
-
|
|
65
|
+
if (taskOptionConflicts.length) {
|
|
66
|
+
error.details += (0, messages_1.formatTaskOptionConflicts)(taskOptionConflicts);
|
|
105
67
|
}
|
|
106
68
|
}
|
|
107
|
-
|
|
69
|
+
const unusedPluginOptions = Object.entries(config.pluginOptions)
|
|
70
|
+
.filter(([, option]) => option && !(0, conflict_1.isConflict)(option) && !option.forPlugin && option.plugin.root === process.cwd())
|
|
71
|
+
.map(([id]) => id);
|
|
72
|
+
if (unusedPluginOptions.length > 0) {
|
|
108
73
|
shouldThrow = true;
|
|
109
|
-
error.details += (0, messages_1.
|
|
74
|
+
error.details += (0, messages_1.formatUnusedPluginOptions)(unusedPluginOptions, Object.keys(config.plugins));
|
|
110
75
|
}
|
|
111
|
-
const
|
|
112
|
-
.filter(([, option]) => option && !(0, conflict_1.isConflict)(option) && !option.
|
|
76
|
+
const unusedTaskOptions = Object.entries(config.taskOptions)
|
|
77
|
+
.filter(([, option]) => option && !(0, conflict_1.isConflict)(option) && !option.task && option.plugin.root === process.cwd())
|
|
113
78
|
.map(([id]) => id);
|
|
114
|
-
if (
|
|
79
|
+
if (unusedTaskOptions.length > 0) {
|
|
115
80
|
shouldThrow = true;
|
|
116
|
-
error.details += (0, messages_1.
|
|
81
|
+
error.details += (0, messages_1.formatUnusedTaskOptions)(unusedTaskOptions, Object.keys(config.tasks));
|
|
117
82
|
}
|
|
118
|
-
const
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
83
|
+
const configuredCommandTasks = (0, conflict_1.withoutConflicts)(Object.values(config.commandTasks));
|
|
84
|
+
const missingTasks = configuredCommandTasks
|
|
85
|
+
.map((command) => ({
|
|
86
|
+
command,
|
|
87
|
+
tasks: command.tasks.filter((task) => !config.tasks[task.task])
|
|
122
88
|
}))
|
|
123
89
|
.filter(({ tasks }) => tasks.length > 0);
|
|
124
90
|
if (missingTasks.length > 0) {
|
|
@@ -131,42 +97,25 @@ function validateConfig(config, logger) {
|
|
|
131
97
|
return validConfig;
|
|
132
98
|
}
|
|
133
99
|
exports.validateConfig = validateConfig;
|
|
134
|
-
function validatePlugins(config) {
|
|
135
|
-
const validatedPlugins = (0, types_1.reduceValidated)(Object.entries(config.plugins).map(([id, plugin]) => (0, types_1.mapValidated)(plugin, (p) => [id, p])));
|
|
136
|
-
return (0, types_1.mapValidated)(validatedPlugins, (plugins) => ({ ...config, plugins: Object.fromEntries(plugins) }));
|
|
137
|
-
}
|
|
138
|
-
exports.validatePlugins = validatePlugins;
|
|
139
|
-
async function checkInstall(config) {
|
|
140
|
-
const definedHooks = (0, conflict_1.withoutConflicts)(Object.values(config.hooks));
|
|
141
|
-
const uninstalledHooks = await asyncFilter(definedHooks, async (hook) => {
|
|
142
|
-
return !(await hook.check());
|
|
143
|
-
});
|
|
144
|
-
if (uninstalledHooks.length > 0) {
|
|
145
|
-
const error = new error_1.ToolKitError('There are problems with your Tool Kit installation.');
|
|
146
|
-
error.details = (0, messages_1.formatUninstalledHooks)(uninstalledHooks);
|
|
147
|
-
throw error;
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
exports.checkInstall = checkInstall;
|
|
151
100
|
async function loadConfig(logger, { validate = true } = {}) {
|
|
152
101
|
const config = (0, exports.createConfig)();
|
|
153
102
|
// start loading config and child plugins, starting from the consumer app directory
|
|
154
103
|
const rootPlugin = await (0, plugin_1.loadPlugin)('app root', config, logger);
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
error
|
|
104
|
+
const validRootPlugin = rootPlugin.unwrap('root plugin was not valid!');
|
|
105
|
+
const validatedPluginConfig = (0, validate_plugins_1.validatePlugins)(config);
|
|
106
|
+
const validPluginConfig = validatedPluginConfig.unwrap('config was not valid!');
|
|
107
|
+
// collate root plugin and descendent hooks, options etc into config
|
|
108
|
+
// start with options so we can substitute resolved values into other parts
|
|
109
|
+
// of the config
|
|
110
|
+
(0, plugin_1.resolvePluginOptions)(validRootPlugin, validPluginConfig);
|
|
111
|
+
const invalidOptions = (0, options_1.validatePluginOptions)(logger, validPluginConfig);
|
|
112
|
+
if (invalidOptions.length > 0 && validate) {
|
|
113
|
+
const error = new error_1.ToolKitError('There are problems with your plugin options.');
|
|
114
|
+
error.details = (0, messages_1.formatInvalidOptions)(invalidOptions);
|
|
165
115
|
throw error;
|
|
166
116
|
}
|
|
167
|
-
|
|
168
|
-
// collate root plugin and descendent hooks, options etc into config
|
|
117
|
+
(0, options_1.substituteOptionTags)(validRootPlugin, validPluginConfig);
|
|
169
118
|
(0, plugin_1.resolvePlugin)(validRootPlugin, validPluginConfig, logger);
|
|
170
|
-
return validate ? validateConfig(validPluginConfig
|
|
119
|
+
return validate ? validateConfig(validPluginConfig) : config;
|
|
171
120
|
}
|
|
172
121
|
exports.loadConfig = loadConfig;
|
package/lib/fetch.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fetch.d.ts","sourceRoot":"","sources":["../src/fetch.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,wBAAwB,QAAO,OAY3C,CAAA"}
|
package/lib/fetch.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.shouldDisableNativeFetch = void 0;
|
|
4
|
+
const options_1 = require("@dotcom-tool-kit/options");
|
|
5
|
+
// function that plugins can check if they need to implement their own logic to
|
|
6
|
+
// disable Node 18's native fetch
|
|
7
|
+
const shouldDisableNativeFetch = () => {
|
|
8
|
+
// disable Node 18's native fetch if the Node runtime supports it (older
|
|
9
|
+
// runtimes don't support the flag, implying they also don't use native
|
|
10
|
+
// fetch) and the user hasn't opted out of the behaviour
|
|
11
|
+
return (
|
|
12
|
+
/* eslint-disable-next-line @typescript-eslint/no-non-null-assertion --
|
|
13
|
+
* the root plugin has default options and it always exists so is always
|
|
14
|
+
* defined
|
|
15
|
+
**/
|
|
16
|
+
!(0, options_1.getOptions)('app root').allowNativeFetch &&
|
|
17
|
+
process.allowedNodeEnvironmentFlags.has('--no-experimental-fetch'));
|
|
18
|
+
};
|
|
19
|
+
exports.shouldDisableNativeFetch = shouldDisableNativeFetch;
|
package/lib/help.d.ts
CHANGED
package/lib/help.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"help.d.ts","sourceRoot":"","sources":["../src/help.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;
|
|
1
|
+
{"version":3,"file":"help.d.ts","sourceRoot":"","sources":["../src/help.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AA4ErC,wBAA8B,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CA4CxF"}
|
package/lib/help.js
CHANGED
|
@@ -1,54 +1,87 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const tslib_1 = require("tslib");
|
|
3
4
|
const config_1 = require("./config");
|
|
4
5
|
const options_1 = require("@dotcom-tool-kit/options");
|
|
5
6
|
const logger_1 = require("@dotcom-tool-kit/logger");
|
|
6
|
-
|
|
7
|
+
const yaml_1 = tslib_1.__importDefault(require("yaml"));
|
|
8
|
+
const endent_1 = tslib_1.__importDefault(require("endent"));
|
|
9
|
+
const toolKitIntro = logger_1.styles.box((0, endent_1.default) `
|
|
10
|
+
Tool Kit is modern, maintainable & modular developer tooling for FT.com projects.
|
|
11
|
+
${logger_1.styles.URL('https://github.com/financial-times/dotcom-tool-kit')}
|
|
12
|
+
`, { title: `🧰 ${logger_1.styles.title(`welcome to ${logger_1.styles.app('Tool Kit')}!`)}` });
|
|
13
|
+
const formatTask = ({ task, options }) => (0, endent_1.default) `
|
|
14
|
+
${logger_1.styles.task(task)}${Object.keys(options).length > 0
|
|
15
|
+
? ` ${logger_1.styles.dim('with options:')}
|
|
16
|
+
${yaml_1.default.stringify(options).trim()}`
|
|
17
|
+
: ''}`;
|
|
18
|
+
const formatCommandTasks = (config, commands) => logger_1.styles.box((0, endent_1.default) `
|
|
19
|
+
${logger_1.styles.help(`${logger_1.styles.command('commands')} run Tool Kit tasks with ${logger_1.styles.code('npx dotcom-tool-kit $command')}, or via configuration installed by hooks in your repository.`)}
|
|
20
|
+
${commands
|
|
21
|
+
.filter((command) => config.commandTasks[command])
|
|
22
|
+
.map((command) => formatCommandTask(command, config.commandTasks[command]))
|
|
23
|
+
.join('\n')}
|
|
24
|
+
|
|
25
|
+
`, {
|
|
26
|
+
title: '⛭ ' + logger_1.styles.title('available commands')
|
|
27
|
+
});
|
|
28
|
+
const formatCommandTask = (command, { tasks, plugin }) => (0, endent_1.default) `
|
|
29
|
+
${logger_1.styles.groupHeader(logger_1.styles.command(command))}
|
|
30
|
+
${tasks.length
|
|
31
|
+
? (0, endent_1.default) `
|
|
32
|
+
${logger_1.styles.info(`${plugin.id !== 'app root' ? `from plugin ${logger_1.styles.plugin(plugin.id)}. ` : ''}runs tasks:`)}
|
|
33
|
+
${tasks.map((task) => ` - ${formatTask(task)}`).join('\n')}
|
|
34
|
+
`
|
|
35
|
+
: logger_1.styles.warning(`no tasks configured to run for ${logger_1.styles.command(command)}`)}
|
|
36
|
+
`;
|
|
37
|
+
const formatHooks = (config) => logger_1.styles.box((0, endent_1.default) `
|
|
38
|
+
${logger_1.styles.help(`${logger_1.styles.hook('hooks')} manage configuration files in your repository, for running Tool Kit commands.`)}
|
|
39
|
+
${Object.entries(config.hooks)
|
|
40
|
+
.map(([hook, entryPoint]) => {
|
|
41
|
+
const managesFiles = entryPoint.plugin.rcFile?.installs[hook].managesFiles ?? [];
|
|
42
|
+
return (0, endent_1.default) `
|
|
43
|
+
${logger_1.styles.groupHeader(logger_1.styles.hook(hook))}
|
|
44
|
+
${logger_1.styles.info((0, endent_1.default) `
|
|
45
|
+
from plugin ${logger_1.styles.plugin(entryPoint.plugin.id)}
|
|
46
|
+
`)}
|
|
47
|
+
${managesFiles.length ? 'manages files:' : ''}
|
|
48
|
+
${managesFiles.map((file) => ` - ${logger_1.styles.filepath(file)}`).join('\n')}
|
|
49
|
+
`;
|
|
50
|
+
})
|
|
51
|
+
.join('\n')}
|
|
52
|
+
`, { title: logger_1.styles.title('🎣 installed hooks') });
|
|
53
|
+
async function showHelp(logger, commands) {
|
|
7
54
|
const config = await (0, config_1.loadConfig)(logger);
|
|
8
|
-
|
|
9
|
-
|
|
55
|
+
const printAllCommands = commands.length === 0;
|
|
56
|
+
if (printAllCommands) {
|
|
57
|
+
commands = Object.keys(config.commandTasks).sort();
|
|
10
58
|
}
|
|
11
|
-
for (const pluginOptions of Object.values(config.
|
|
59
|
+
for (const pluginOptions of Object.values(config.pluginOptions)) {
|
|
12
60
|
if (pluginOptions.forPlugin) {
|
|
13
61
|
(0, options_1.setOptions)(pluginOptions.forPlugin.id, pluginOptions.options);
|
|
14
62
|
}
|
|
15
63
|
}
|
|
16
|
-
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
? 'available hooks'
|
|
30
|
-
: `help for ${hooks.length - missingHooks.length} ${hooks.length - missingHooks.length > 1 ? 'hooks' : 'hook'}`)}:
|
|
31
|
-
`);
|
|
32
|
-
for (const hook of hooks) {
|
|
33
|
-
const Hook = config.hooks[hook];
|
|
34
|
-
if (Hook) {
|
|
35
|
-
const tasks = config.hookTasks[hook];
|
|
36
|
-
/* eslint-disable @typescript-eslint/no-explicit-any -- Object.constructor does not consider static properties */
|
|
37
|
-
logger.info(`${logger_1.styles.heading(hook)}
|
|
38
|
-
${Hook.constructor.description ? Hook.constructor.description + '\n' : ''}
|
|
39
|
-
${tasks && tasks.tasks.length
|
|
40
|
-
? `runs ${tasks.tasks.length > 1 ? 'these tasks' : 'this task'}:
|
|
41
|
-
${tasks.tasks
|
|
42
|
-
.map((task) => `- ${logger_1.styles.task(task)} ${logger_1.styles.dim(config.tasks[task].description)}`)
|
|
43
|
-
.join('\n')}`
|
|
44
|
-
: logger_1.styles.dim('no tasks configured to run on this hook.')}
|
|
45
|
-
${logger_1.styles.ruler()}
|
|
46
|
-
`);
|
|
47
|
-
/*eslint-enable @typescript-eslint/no-explicit-any */
|
|
48
|
-
}
|
|
64
|
+
logger.info(toolKitIntro);
|
|
65
|
+
const definedCommands = commands.filter((command) => config.commandTasks[command]);
|
|
66
|
+
const missingCommands = commands.filter((command) => !config.commandTasks[command]);
|
|
67
|
+
if (printAllCommands && Object.keys(config.hooks).length) {
|
|
68
|
+
logger.info(formatHooks(config));
|
|
69
|
+
}
|
|
70
|
+
if (Object.keys(config.commandTasks).length === 0) {
|
|
71
|
+
logger.warn(logger_1.styles.warning((0, endent_1.default) `
|
|
72
|
+
there are no commands available. add some commands by defining them in your ${logger_1.styles.filepath('.toolkitrc.yml')} or installing plugins that define commands.
|
|
73
|
+
`));
|
|
74
|
+
}
|
|
75
|
+
else if (definedCommands.length > 0) {
|
|
76
|
+
logger.info(formatCommandTasks(config, definedCommands));
|
|
49
77
|
}
|
|
50
|
-
if (
|
|
51
|
-
logger.warn(
|
|
78
|
+
else if (missingCommands.length) {
|
|
79
|
+
logger.warn(logger_1.styles.error((0, endent_1.default) `
|
|
80
|
+
no such ${missingCommands.length > 1 ? 'commands' : 'command'} ${missingCommands
|
|
81
|
+
.map((id) => logger_1.styles.command(id))
|
|
82
|
+
.join(', ')}
|
|
83
|
+
`));
|
|
52
84
|
}
|
|
85
|
+
logger.info('\n');
|
|
53
86
|
}
|
|
54
87
|
exports.default = showHelp;
|
package/lib/index.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import type { Logger } from 'winston';
|
|
2
|
-
export
|
|
3
|
-
export
|
|
2
|
+
export { runTasks } from './tasks';
|
|
3
|
+
export { shouldDisableNativeFetch } from './fetch';
|
|
4
4
|
export declare function listPlugins(logger: Logger): Promise<void>;
|
|
5
|
-
export
|
|
6
|
-
export { default as installHooks } from './install';
|
|
5
|
+
export declare function printConfig(logger: Logger): Promise<void>;
|
|
7
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":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AAIrC,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAClC,OAAO,EAAE,wBAAwB,EAAE,MAAM,SAAS,CAAA;AAElD,wBAAsB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAO/D;AAED,wBAAsB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAI/D"}
|