create-gasket-app 7.0.1-cli.0 → 7.0.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.
Files changed (35) hide show
  1. package/README.md +223 -3
  2. package/lib/commands/create.js +149 -0
  3. package/lib/config/default-plugins.js +15 -0
  4. package/lib/index.d.ts +309 -0
  5. package/lib/index.js +24 -9
  6. package/lib/scaffold/action-wrapper.js +37 -0
  7. package/lib/scaffold/actions/create-hooks.js +27 -0
  8. package/lib/scaffold/actions/generate-files.js +189 -0
  9. package/lib/scaffold/actions/global-prompts.js +153 -0
  10. package/lib/scaffold/actions/index.js +33 -0
  11. package/lib/scaffold/actions/install-modules.js +15 -0
  12. package/lib/scaffold/actions/link-modules.js +19 -0
  13. package/lib/scaffold/actions/load-preset.js +60 -0
  14. package/lib/scaffold/actions/mkdir.js +30 -0
  15. package/lib/scaffold/actions/post-create-hooks.js +31 -0
  16. package/lib/scaffold/actions/preset-config-hooks.js +13 -0
  17. package/lib/scaffold/actions/preset-prompt-hooks.js +17 -0
  18. package/lib/scaffold/actions/print-report.js +89 -0
  19. package/lib/scaffold/actions/prompt-hooks.js +43 -0
  20. package/lib/scaffold/actions/setup-pkg.js +34 -0
  21. package/lib/scaffold/actions/write-gasket-config.js +119 -0
  22. package/lib/scaffold/actions/write-pkg.js +19 -0
  23. package/lib/scaffold/config-builder.js +526 -0
  24. package/lib/scaffold/create-context.js +188 -0
  25. package/lib/scaffold/dump-error-context.js +28 -0
  26. package/lib/scaffold/files.js +30 -0
  27. package/lib/scaffold/readme.js +51 -0
  28. package/lib/scaffold/utils.js +22 -0
  29. package/lib/utils/create-option.js +18 -0
  30. package/lib/utils/index.js +5 -0
  31. package/lib/utils/logo.js +12 -0
  32. package/lib/utils/process-args.js +37 -0
  33. package/lib/utils/process-command.js +50 -0
  34. package/lib/utils/process-options.js +44 -0
  35. 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,5 @@
1
+ export { processCommand } from './process-command.js';
2
+ export { processArgs } from './process-args.js';
3
+ export { processOptions } from './process-options.js';
4
+ export { createOption } from './create-option.js';
5
+ export { logo } from './logo.js';
@@ -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.1-cli.0",
3
+ "version": "7.0.1",
4
4
  "description": "starter pack for creating a gasket app",
5
- "main": "lib",
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": "jest --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/cli": "^7.0.1-cli.0"
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.1",
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.0.2",
40
- "eslint-plugin-jest": "^27.6.3",
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": "^44.0.0",
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
- "gitHead": "c0c28ee8ad4ab7ed4592f0e962ca3403909916cf"
84
+ "jest": {
85
+ "transform": {}
86
+ },
87
+ "gitHead": "0426b7f57bc2618606955912c0f3cd55174f5367"
61
88
  }