create-gasket-app 7.0.3-cli.0 → 7.0.3
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/README.md +223 -3
- package/lib/commands/create.js +149 -0
- package/lib/config/default-plugins.js +15 -0
- package/lib/index.d.ts +310 -0
- package/lib/index.js +24 -9
- package/lib/scaffold/action-wrapper.js +37 -0
- package/lib/scaffold/actions/create-hooks.js +27 -0
- package/lib/scaffold/actions/generate-files.js +189 -0
- package/lib/scaffold/actions/global-prompts.js +153 -0
- package/lib/scaffold/actions/index.js +33 -0
- package/lib/scaffold/actions/install-modules.js +15 -0
- package/lib/scaffold/actions/link-modules.js +19 -0
- package/lib/scaffold/actions/load-preset.js +60 -0
- package/lib/scaffold/actions/mkdir.js +30 -0
- package/lib/scaffold/actions/post-create-hooks.js +31 -0
- package/lib/scaffold/actions/preset-config-hooks.js +13 -0
- package/lib/scaffold/actions/preset-prompt-hooks.js +17 -0
- package/lib/scaffold/actions/print-report.js +89 -0
- package/lib/scaffold/actions/prompt-hooks.js +43 -0
- package/lib/scaffold/actions/setup-pkg.js +34 -0
- package/lib/scaffold/actions/write-gasket-config.js +119 -0
- package/lib/scaffold/actions/write-pkg.js +19 -0
- package/lib/scaffold/config-builder.js +526 -0
- package/lib/scaffold/create-context.js +188 -0
- package/lib/scaffold/dump-error-context.js +28 -0
- package/lib/scaffold/files.js +30 -0
- package/lib/scaffold/readme.js +51 -0
- package/lib/scaffold/utils.js +22 -0
- package/lib/utils/create-option.js +18 -0
- package/lib/utils/index.js +5 -0
- package/lib/utils/logo.js +12 -0
- package/lib/utils/process-args.js +37 -0
- package/lib/utils/process-command.js +50 -0
- package/lib/utils/process-options.js +44 -0
- package/package.json +36 -9
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import { writeFile } from 'fs/promises';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* If an error occurs during create, dump the context for debugging.
|
|
6
|
+
* The error which cause the exit is also included in the log.
|
|
7
|
+
*
|
|
8
|
+
* @param {CreateContext} context - Create context
|
|
9
|
+
* @param {Error} error - Exiting error
|
|
10
|
+
* @returns {Promise<void>} promise
|
|
11
|
+
*/
|
|
12
|
+
export async function dumpErrorContext(context, error) {
|
|
13
|
+
const { cwd } = context;
|
|
14
|
+
|
|
15
|
+
try {
|
|
16
|
+
const report = { exitError: error.stack, ...context };
|
|
17
|
+
const fileName = 'gasket-create-error.log';
|
|
18
|
+
|
|
19
|
+
const filePath = path.join(cwd, fileName);
|
|
20
|
+
await writeFile(filePath, JSON.stringify(report, null, 2), 'utf8');
|
|
21
|
+
console.log(`Error log dumped to: ${filePath}`);
|
|
22
|
+
} catch (err) {
|
|
23
|
+
//
|
|
24
|
+
// eat but print any errors during writing log file
|
|
25
|
+
//
|
|
26
|
+
console.error(`Error writing error log: ${err}`);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utility for plugins to add files and templates for generating
|
|
3
|
+
*
|
|
4
|
+
* @type {Files}
|
|
5
|
+
*/
|
|
6
|
+
export class Files {
|
|
7
|
+
constructor() {
|
|
8
|
+
this.globSets = [];
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Return array of globs
|
|
13
|
+
*
|
|
14
|
+
* @deprecated
|
|
15
|
+
* @returns {string[]} `globby` compatible patterns
|
|
16
|
+
*/
|
|
17
|
+
get globs() {
|
|
18
|
+
return this.globSets.reduce((acc, cur) => [...acc, ...cur.globs], []);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Adds the specified `globby` compatible patterns, `globs`,
|
|
23
|
+
* into the set of all sources for this set of files.
|
|
24
|
+
* @param {string[]} globs - `globby` compatible patterns
|
|
25
|
+
* @param {Object} source - Plugin to blame if conflicts arise from this operation.
|
|
26
|
+
*/
|
|
27
|
+
add({ globs, source }) {
|
|
28
|
+
this.globSets.push({ globs, source });
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { readFile } from 'fs/promises';
|
|
2
|
+
|
|
3
|
+
/** @type {import('../index').Readme} */
|
|
4
|
+
export default class Readme {
|
|
5
|
+
constructor() {
|
|
6
|
+
this.markdown = [];
|
|
7
|
+
this.links = [];
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
addNewLine() {
|
|
11
|
+
this.markdown.push('');
|
|
12
|
+
return this;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
heading(content, level = 2) {
|
|
16
|
+
this.markdown.push(`${'#'.repeat(level)} ${content}`);
|
|
17
|
+
return this.addNewLine();
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
subHeading(content) {
|
|
21
|
+
return this.heading(content, 3);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
content(content) {
|
|
25
|
+
this.markdown.push(content);
|
|
26
|
+
return this.addNewLine();
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
list(items) {
|
|
30
|
+
this.markdown.push(...items.map(item => `- ${item}`));
|
|
31
|
+
return this.addNewLine();
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
link(content, href) {
|
|
35
|
+
this.links.push(`[${content}]: ${href}`);
|
|
36
|
+
return this;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
codeBlock(content, syntax = '') {
|
|
40
|
+
this.markdown.push(`\`\`\`${syntax}`);
|
|
41
|
+
this.markdown.push(content);
|
|
42
|
+
this.markdown.push('```');
|
|
43
|
+
return this.addNewLine();
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
async markdownFile(path) {
|
|
47
|
+
const content = await readFile(path, 'utf8');
|
|
48
|
+
this.markdown.push(content);
|
|
49
|
+
return this.addNewLine();
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import { createRequire } from 'module';
|
|
3
|
+
const require = createRequire(import.meta.url);
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Parses JSON file or string to assign to context
|
|
7
|
+
*
|
|
8
|
+
* @param {CreateContext} context - Create context.
|
|
9
|
+
* @param {Object} configFlags - flags to read config from
|
|
10
|
+
* @param {string} configFlags.config - JSON string of config values
|
|
11
|
+
* @param {string} configFlags.configFile - path to JSON file of config values
|
|
12
|
+
*/
|
|
13
|
+
export function readConfig(context, { config, configFile }) {
|
|
14
|
+
if (config) {
|
|
15
|
+
const parsedConfig = JSON.parse(config);
|
|
16
|
+
Object.assign(context, parsedConfig);
|
|
17
|
+
} else if (configFile) {
|
|
18
|
+
const parsedConfigFile = require(path.resolve(context.cwd, configFile));
|
|
19
|
+
Object.assign(context, parsedConfigFile);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Option } from 'commander';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* createOption - Create a commander option
|
|
5
|
+
* @param {CLICommandOption} definition - The option configuration
|
|
6
|
+
* @returns {CommnaderOption} option
|
|
7
|
+
*/
|
|
8
|
+
export function createOption(definition) {
|
|
9
|
+
const option = new Option(...definition.options);
|
|
10
|
+
const { defaultValue, conflicts, parse, hidden, required } = definition;
|
|
11
|
+
|
|
12
|
+
if (conflicts.length) option.conflicts(definition.conflicts);
|
|
13
|
+
if (hidden) option.hideHelp();
|
|
14
|
+
if (typeof defaultValue !== 'undefined') option.default(defaultValue);
|
|
15
|
+
if (parse) option.argParser(parse);
|
|
16
|
+
if (required) option.makeOptionMandatory();
|
|
17
|
+
return option;
|
|
18
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export const logo = `
|
|
2
|
+
▄▄▄▄████▀▀█▄
|
|
3
|
+
▄████▀▀▀▀▀▀█▄▄██
|
|
4
|
+
███▀ ▄▄▄▄▄ ▀██▌ ▄▄▄
|
|
5
|
+
▄███ ███▀▀▀▀██ ██ ██ ██
|
|
6
|
+
█▀▀█ ██▌ ▐█▌ ▄▀▀▀█▄ ▄█▀▀▀▄ ██ ▐██▀ ▄█▀▀█▄ ▀██▀▀
|
|
7
|
+
█▄▄█ ██▌ ▀▀██ ▐█▌ ▄▄▄▄██ ▀▀█▄▄▄ █████ ██▄▄██ ██
|
|
8
|
+
▀███ ███▄▄▄▄██ ██ ▀▄▄▄▀█▄ ▀▄▄▄█▀ ▄██▄ ██▄ ▀█▄▄▄▄ ▀█▄▄
|
|
9
|
+
███▄ ▀▀▀ ▀▀ ▄██▌
|
|
10
|
+
▀████▄▄▄▄▄▄█▀▀██
|
|
11
|
+
▀▀▀▀████▄▄█▀
|
|
12
|
+
`;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* isValidArg - Validates the argument configuration
|
|
3
|
+
* @param {CLICommandArg} arg The argument configuration
|
|
4
|
+
* @returns {boolean} True if valid, false otherwise
|
|
5
|
+
*/
|
|
6
|
+
function isValidArg(arg) {
|
|
7
|
+
const keys = Object.keys(arg);
|
|
8
|
+
if (arg.required && arg.default) return false;
|
|
9
|
+
return keys.length &&
|
|
10
|
+
keys.length <= 4 &&
|
|
11
|
+
arg.name && arg.description;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* processArgs - Process the arguments configuration
|
|
16
|
+
* @param {CLICommandArg[]} args Array of argument configurations
|
|
17
|
+
* @returns {ProccesedCLICommandArg[]} Array of argument definitions
|
|
18
|
+
*/
|
|
19
|
+
export function processArgs(args) {
|
|
20
|
+
if (!Array.isArray(args) || !args.every(isValidArg)) throw new Error('Invalid argument(s) configuration');
|
|
21
|
+
|
|
22
|
+
return args.reduce((acc, arg) => {
|
|
23
|
+
const def = [];
|
|
24
|
+
const { name, description, required = false, default: defaultValue } = arg;
|
|
25
|
+
if (required) {
|
|
26
|
+
def.push(`<${name}>`, description);
|
|
27
|
+
} else {
|
|
28
|
+
def.push(`[${name}]`, description);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (defaultValue) def.push(defaultValue);
|
|
32
|
+
|
|
33
|
+
acc.push(def);
|
|
34
|
+
return acc;
|
|
35
|
+
|
|
36
|
+
}, []);
|
|
37
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import { processArgs } from './process-args.js';
|
|
3
|
+
import { processOptions } from './process-options.js';
|
|
4
|
+
import { createOption } from './create-option.js';
|
|
5
|
+
const program = new Command();
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* isValidCommand - Validates the command configuration
|
|
9
|
+
* @param {CLICommand} command The command configuration
|
|
10
|
+
* @returns {boolean} True if valid, false otherwise
|
|
11
|
+
*/
|
|
12
|
+
function isValidCommand(command) {
|
|
13
|
+
const keys = Object.keys(command);
|
|
14
|
+
return keys.length &&
|
|
15
|
+
keys.length <= 7 &&
|
|
16
|
+
command &&
|
|
17
|
+
command.id &&
|
|
18
|
+
command.description &&
|
|
19
|
+
command.action &&
|
|
20
|
+
typeof command.action === 'function';
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* processCommand - Process the command configuration
|
|
25
|
+
* @param {CLICommand} command The command configuration
|
|
26
|
+
* @returns {ProccesedCLICommand} The command instance
|
|
27
|
+
*/
|
|
28
|
+
export function processCommand(command) {
|
|
29
|
+
if (!isValidCommand(command)) throw new Error('Invalid command configuration');
|
|
30
|
+
const { id, description, action, args, options, hidden = false, default: isDefault = false } = command;
|
|
31
|
+
const cmd = program
|
|
32
|
+
.command(id)
|
|
33
|
+
.description(description)
|
|
34
|
+
.action(action);
|
|
35
|
+
|
|
36
|
+
if (args) {
|
|
37
|
+
const cmdArgs = processArgs(args);
|
|
38
|
+
cmdArgs.forEach(arg => cmd.argument(...arg));
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (options) {
|
|
42
|
+
const cmdOpts = processOptions(options);
|
|
43
|
+
cmdOpts.forEach(o => {
|
|
44
|
+
const option = createOption(o);
|
|
45
|
+
cmd.addOption(option);
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return { command: cmd, hidden, isDefault };
|
|
50
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* isValidOption - Validate the option
|
|
3
|
+
* @param {CLICommandOption} option The option configuration
|
|
4
|
+
* @returns {boolean} True if valid, false otherwise
|
|
5
|
+
*/
|
|
6
|
+
function isValidOption(option) {
|
|
7
|
+
const keys = Object.keys(option);
|
|
8
|
+
return keys.length &&
|
|
9
|
+
keys.length <= 5 &&
|
|
10
|
+
option.name &&
|
|
11
|
+
option.description;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* processOptions - Process the options configuration
|
|
16
|
+
* @param {CLICommandOption[]} options Array of option configurations
|
|
17
|
+
* @returns {ProccesedCLICommandOption[]} Processed option definitions
|
|
18
|
+
*/
|
|
19
|
+
export function processOptions(options) {
|
|
20
|
+
if (!Array.isArray(options) || !options.every(isValidOption)) throw new Error('Invalid option(s) configuration');
|
|
21
|
+
|
|
22
|
+
return options.reduce((acc, option) => {
|
|
23
|
+
const def = [];
|
|
24
|
+
const {
|
|
25
|
+
name,
|
|
26
|
+
description,
|
|
27
|
+
required = false,
|
|
28
|
+
short,
|
|
29
|
+
parse,
|
|
30
|
+
type = 'string',
|
|
31
|
+
conflicts = [],
|
|
32
|
+
hidden = false,
|
|
33
|
+
default: defaultValue
|
|
34
|
+
} = option;
|
|
35
|
+
|
|
36
|
+
const format = required ? `<${name}>` : `[${name}]`;
|
|
37
|
+
const flags = short ? `-${short}, --${name}` : `--${name}`;
|
|
38
|
+
|
|
39
|
+
def.push(`${flags}${type !== 'boolean' ? ` ${format}` : ''}`, description);
|
|
40
|
+
acc.push({ options: def, conflicts, hidden, defaultValue, parse, required });
|
|
41
|
+
|
|
42
|
+
return acc;
|
|
43
|
+
}, []);
|
|
44
|
+
}
|
package/package.json
CHANGED
|
@@ -1,19 +1,21 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-gasket-app",
|
|
3
|
-
"version": "7.0.3
|
|
3
|
+
"version": "7.0.3",
|
|
4
4
|
"description": "starter pack for creating a gasket app",
|
|
5
|
-
"
|
|
5
|
+
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"create-gasket-app": "./lib/index.js"
|
|
8
8
|
},
|
|
9
|
+
"main": "lib/index.js",
|
|
10
|
+
"types": "lib/index.d.ts",
|
|
9
11
|
"files": [
|
|
10
12
|
"lib"
|
|
11
13
|
],
|
|
12
14
|
"scripts": {
|
|
13
15
|
"lint": "eslint .",
|
|
14
16
|
"lint:fix": "npm run lint -- --fix",
|
|
15
|
-
"test": "cross-env NODE_OPTIONS='--unhandled-rejections=strict' jest",
|
|
16
|
-
"test:watch": "
|
|
17
|
+
"test": "cross-env NODE_OPTIONS='--unhandled-rejections=strict --experimental-vm-modules' jest",
|
|
18
|
+
"test:watch": "npm run test -- --watch",
|
|
17
19
|
"test:coverage": "jest --coverage",
|
|
18
20
|
"posttest": "npm run lint"
|
|
19
21
|
},
|
|
@@ -31,15 +33,37 @@
|
|
|
31
33
|
},
|
|
32
34
|
"homepage": "https://github.com/godaddy/gasket/tree/main/packages/create-gasket-app",
|
|
33
35
|
"dependencies": {
|
|
34
|
-
"@gasket/
|
|
36
|
+
"@gasket/core": "^7.0.1",
|
|
37
|
+
"@gasket/plugin-command": "^7.0.1",
|
|
38
|
+
"@gasket/plugin-docs": "^7.0.1",
|
|
39
|
+
"@gasket/plugin-docusaurus": "^7.0.3",
|
|
40
|
+
"@gasket/plugin-git": "^7.0.1",
|
|
41
|
+
"@gasket/plugin-logger": "^7.0.1",
|
|
42
|
+
"@gasket/plugin-metadata": "^7.0.1",
|
|
43
|
+
"@gasket/utils": "^7.0.1",
|
|
44
|
+
"commander": "^12.0.0",
|
|
45
|
+
"deepmerge": "^4.3.1",
|
|
46
|
+
"glob": "^8.1.0",
|
|
47
|
+
"handlebars": "^4.7.8",
|
|
48
|
+
"inquirer": "6.5.2",
|
|
49
|
+
"json5": "^2.2.3",
|
|
50
|
+
"mkdirp": "^1.0.4",
|
|
51
|
+
"ora": "3.4.0",
|
|
52
|
+
"pump": "^3.0.0",
|
|
53
|
+
"semver": "^7.5.4",
|
|
54
|
+
"tar-fs": "^2.0.0",
|
|
55
|
+
"untildify": "^4.0.0"
|
|
35
56
|
},
|
|
36
57
|
"devDependencies": {
|
|
58
|
+
"@types/inquirer": "^9.0.7",
|
|
37
59
|
"cross-env": "^7.0.3",
|
|
60
|
+
"diagnostics": "^2.0.2",
|
|
61
|
+
"dotenv": "^16.4.5",
|
|
38
62
|
"eslint": "^8.56.0",
|
|
39
|
-
"eslint-config-godaddy": "^7.
|
|
40
|
-
"eslint-plugin-jest": "^
|
|
63
|
+
"eslint-config-godaddy": "^7.1.1",
|
|
64
|
+
"eslint-plugin-jest": "^28.6.0",
|
|
41
65
|
"eslint-plugin-json": "^3.1.0",
|
|
42
|
-
"eslint-plugin-unicorn": "^
|
|
66
|
+
"eslint-plugin-unicorn": "^55.0.0",
|
|
43
67
|
"jest": "^29.7.0"
|
|
44
68
|
},
|
|
45
69
|
"eslintConfig": {
|
|
@@ -57,5 +81,8 @@
|
|
|
57
81
|
"eslintIgnore": [
|
|
58
82
|
"test/fixtures"
|
|
59
83
|
],
|
|
60
|
-
"
|
|
84
|
+
"jest": {
|
|
85
|
+
"transform": {}
|
|
86
|
+
},
|
|
87
|
+
"gitHead": "b023043d772b31c25dfd49e6b17bfb21ad54555d"
|
|
61
88
|
}
|