create-gasket-app 7.0.2-cli.0 → 7.2.0-canary.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.
Files changed (34) hide show
  1. package/README.md +222 -2
  2. package/lib/commands/create.js +148 -0
  3. package/lib/config/default-plugins.js +7 -0
  4. package/lib/index.d.ts +264 -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 +25 -0
  8. package/lib/scaffold/actions/generate-files.js +185 -0
  9. package/lib/scaffold/actions/global-prompts.js +158 -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 +117 -0
  22. package/lib/scaffold/actions/write-pkg.js +19 -0
  23. package/lib/scaffold/config-builder.js +523 -0
  24. package/lib/scaffold/create-context.js +187 -0
  25. package/lib/scaffold/dump-error-context.js +28 -0
  26. package/lib/scaffold/files.js +30 -0
  27. package/lib/scaffold/utils.js +22 -0
  28. package/lib/utils/create-option.js +18 -0
  29. package/lib/utils/index.js +5 -0
  30. package/lib/utils/logo.js +12 -0
  31. package/lib/utils/process-args.js +37 -0
  32. package/lib/utils/process-command.js +50 -0
  33. package/lib/utils/process-options.js +44 -0
  34. package/package.json +29 -7
@@ -0,0 +1,89 @@
1
+ import pkg from 'chalk';
2
+ const { bold } = pkg;
3
+ import action from '../action-wrapper.js';
4
+ import { logo } from '../../utils/index.js';
5
+
6
+ /**
7
+ * Logs a new line in the console
8
+ * @private
9
+ */
10
+ const newline = () => {
11
+ console.log('');
12
+ };
13
+
14
+ /**
15
+ * Converts a camelCase string to Space Case
16
+ * @see: https://stackoverflow.com/questions/4149276/javascript-camelcase-to-regular-form?answertab=active#tab-top
17
+ *
18
+ * @param {string} str - camelCase string to fixup
19
+ * @returns {string} result
20
+ * @private
21
+ */
22
+ const toSpaceCase = str => str.replace(/([A-Z])/g, ' $1')
23
+ .replace(/^./, s => s.toUpperCase());
24
+
25
+ /**
26
+ * Builds the report object from context
27
+ *
28
+ * @param {CreateContext} context - Create context
29
+ * @returns {Object} report
30
+ * @private
31
+ */
32
+ function buildReport(context) {
33
+ const {
34
+ appName,
35
+ dest,
36
+ fullPresets,
37
+ plugins,
38
+ generatedFiles: generatedFilesSet,
39
+ messages,
40
+ warnings,
41
+ errors,
42
+ nextSteps
43
+ } = context;
44
+
45
+ const generatedFiles = Array.from(generatedFilesSet);
46
+ generatedFiles.sort();
47
+
48
+ return {
49
+ appName,
50
+ output: dest,
51
+ presets: fullPresets,
52
+ plugins,
53
+ generatedFiles,
54
+ messages,
55
+ warnings,
56
+ errors,
57
+ nextSteps
58
+ };
59
+ }
60
+
61
+ /**
62
+ * Outputs create command details to the console
63
+
64
+ * @param {CreateContext} context - Create context
65
+ */
66
+ async function printReport({ context }) {
67
+ const report = buildReport(context);
68
+ const { warnings, errors } = context;
69
+
70
+ console.log(`✨Success!
71
+
72
+ Finished with ${warnings.length} warnings and ${errors.length} errors using
73
+ ` + logo);
74
+
75
+ Object.entries(report).forEach(([k, v]) => {
76
+ if (!v || !v.length) return;
77
+ newline();
78
+ console.log(`${bold(toSpaceCase(k))}`);
79
+ if (Array.isArray(v)) {
80
+ v.map(o => console.log(` ${o}`));
81
+ } else {
82
+ console.log(` ${v}`);
83
+ }
84
+ });
85
+
86
+ newline();
87
+ }
88
+
89
+ export default action('Print report', printReport, { startSpinner: false });
@@ -0,0 +1,43 @@
1
+ import inquirer from 'inquirer';
2
+ import action from '../action-wrapper.js';
3
+
4
+ /**
5
+ * Initializes engine with provide preset and plugins
6
+ * to execute their prompt lifecycle hooks.
7
+ *
8
+ * @param {CreateContext} context - Create context
9
+ * @param {String[]} plugins - plugins to load
10
+ * @param {String} [presets] - presets to load
11
+ * @returns {Promise} promise
12
+ * @private
13
+ */
14
+ async function execPluginPrompts(gasket, context) {
15
+ //
16
+ // @see: https://github.com/SBoudrias/Inquirer.js/#inquirercreatepromptmodule---prompt-function
17
+ //
18
+ const prompt = context.prompts ? inquirer.createPromptModule() : () => ({});
19
+ const nextContext = await gasket.execWaterfall('prompt', context, { prompt });
20
+ //
21
+ // Ensure the original context is transformed in case a prompt returns a new object
22
+ //
23
+ Object.assign(context, nextContext);
24
+ }
25
+
26
+ /**
27
+ * Executes the `prompt` hook for all registered plugins.
28
+ * Adds `prompt` util function for prompting features.
29
+ *
30
+ * @param {GasketEngine} gasket - Gasket API
31
+ * @param {CreateContext} context - Create context
32
+ * @returns {Promise} promise
33
+ */
34
+ async function promptHooks({ gasket, context }) {
35
+ //
36
+ // Because `execPluginPrompts` is recursively, we need to start it
37
+ // with the processPlugins and presets from our initial context
38
+ //
39
+ const { plugins } = context;
40
+ await execPluginPrompts(gasket, context, plugins);
41
+ }
42
+
43
+ export default action('Plugin prompts', promptHooks, { startSpinner: false });
@@ -0,0 +1,34 @@
1
+ import action from '../action-wrapper.js';
2
+ import { ConfigBuilder } from '../config-builder.js';
3
+ import { default as gasketUtils } from '@gasket/utils';
4
+ import { createRequire } from 'module';
5
+ const require = createRequire(import.meta.url);
6
+ const { dependencies } = require('../../../package.json');
7
+
8
+ /**
9
+ * Initializes the ConfigBuilder builder and adds to context.
10
+ *
11
+ * @param {CreateContext} context - Create context
12
+ * @returns {Promise} promise
13
+ */
14
+ async function setupPkg({ context }) {
15
+ const { appName, appDescription, warnings } = context;
16
+
17
+ const pkg = ConfigBuilder.createPackageJson({
18
+ name: appName,
19
+ version: '0.0.0',
20
+ description: appDescription,
21
+ type: 'module'
22
+ }, { warnings });
23
+
24
+ // Add critical dependencies
25
+ pkg.add('dependencies', {
26
+ '@gasket/core': dependencies['@gasket/core'],
27
+ '@gasket/utils': dependencies['@gasket/utils']
28
+ });
29
+
30
+ const pkgManager = new gasketUtils.PackageManager(context);
31
+ Object.assign(context, { pkg, pkgManager });
32
+ }
33
+
34
+ export default action('Set up package.json', setupPkg, { startSpinner: false });
@@ -0,0 +1,117 @@
1
+ import { default as JSON5 } from 'json5';
2
+ import path from 'path';
3
+ import { writeFile } from 'fs/promises';
4
+ import action from '../action-wrapper.js';
5
+
6
+ /**
7
+ * writePluginImports - Write string imports as value(s)
8
+ * @param {string[]} plugins - Array of plugin import names
9
+ * @returns {string} - Array of plugin imports as string
10
+ */
11
+ function writePluginImports(plugins) {
12
+ return plugins.reduce((acc, cur, index) => {
13
+ acc += `\t\t${cur}${index < plugins.length - 1 ? ',\n' : ''}`;
14
+ return acc;
15
+ }, '');
16
+ }
17
+
18
+ /**
19
+ * writeImports - Write imports to file using key value pairs
20
+ * @param {{[pluginImport: string]: string}[]} imports - Array of key value pairs for imports
21
+ * @returns {string} - import declarations as string
22
+ */
23
+ function writeImports(imports) {
24
+ if (!imports) return '';
25
+ return `${Object.entries(imports).map(([importDef, importPath]) => `import ${importDef} from '${importPath}';`).join('\n')}\n`;
26
+ }
27
+
28
+ /**
29
+ * createInjectionAssignments - replace object path with a temp string value
30
+ * @param {GasketConfigDefinition} config - gasket config object
31
+ * @param {{ [configKey]: string }} assignments - key value pairs of config keys to replace
32
+ * @returns {string} - string if assignments is falsy
33
+ */
34
+ function createInjectionAssignments(config, assignments) {
35
+ if (!assignments) return '';
36
+ Object.keys(assignments).forEach((key) => {
37
+ const keys = key.split('.');
38
+
39
+ keys.reduce((acc, cur, index) => {
40
+ if (index === keys.length - 1) {
41
+ acc[cur] = `${key}_INJECTION_ASSIGNMENT_REPLACE`;
42
+ return;
43
+ }
44
+ return acc[cur];
45
+ }, config);
46
+ });
47
+ }
48
+
49
+ /**
50
+ * replaceInjectionAssignments - replace temp string value with actual value
51
+ * @param {string} content
52
+ * @param {{ [configKey]: string }} assignments - key value pairs of config keys to replace
53
+ * @returns {string} - content with replaced values
54
+ */
55
+ function replaceInjectionAssignments(content, assignments) {
56
+ if (!assignments) return content;
57
+ Object.keys(assignments).forEach((key) => {
58
+ content = content.replace(`'${key}_INJECTION_ASSIGNMENT_REPLACE'`, assignments[key]);
59
+ });
60
+
61
+ return content;
62
+ }
63
+
64
+ /**
65
+ * writeExpressions - Write expressions to file
66
+ * @param {string} expressions - programmatic expressions as string
67
+ * @returns {string} - expressions as string
68
+ */
69
+ function writeExpressions(expressions) {
70
+ if (!expressions) return '';
71
+ return `${expressions.map((expression) => `${expression}`).join('\n')}\n`;
72
+ }
73
+
74
+ /**
75
+ * cleanupFields - Remove fields from config object
76
+ * @param {GasketConfigDefinition} config - gasket config object
77
+ */
78
+ function cleanupFields(config) {
79
+ delete config.fields.imports;
80
+ delete config.fields.pluginImports;
81
+ delete config.fields.expressions;
82
+ delete config.fields.injectionAssignments;
83
+ }
84
+
85
+ /**
86
+ * Writes the contents of `pkg` to the app's package.json.
87
+ *
88
+ * @param {CreateContext} context - Create context
89
+ * @returns {Promise} promise
90
+ */
91
+ async function writeGasketConfig({ context }) {
92
+ const { dest, gasketConfig, generatedFiles } = context;
93
+ const fileName = context.typescript ? 'gasket.ts' : 'gasket.js';
94
+ const filePath = path.join(dest, fileName);
95
+ const plugins = gasketConfig.fields.plugins;
96
+ const assignments = gasketConfig.fields.injectionAssignments || null;
97
+ const expressions = gasketConfig.fields.expressions || null;
98
+ gasketConfig.fields.plugins = 'PLUGIN_REPLACE';
99
+
100
+ let contents = '';
101
+ contents += `import { makeGasket } from '@gasket/core';\n`;
102
+ contents += writeImports(gasketConfig.fields.pluginImports);
103
+ contents += writeImports(gasketConfig.fields.imports);
104
+ contents += writeExpressions(expressions);
105
+ createInjectionAssignments(gasketConfig.fields, assignments);
106
+ cleanupFields(gasketConfig);
107
+
108
+ const pluginImports = `[\n${writePluginImports(plugins)}\n\t]`;
109
+ contents += `\nexport default makeGasket(${JSON5.stringify(gasketConfig.fields, null, 2)});\n`;
110
+ contents = contents.replace('\'PLUGIN_REPLACE\'', pluginImports);
111
+ contents = replaceInjectionAssignments(contents, assignments);
112
+
113
+ await writeFile(filePath, contents, 'utf8');
114
+ generatedFiles.add(fileName);
115
+ }
116
+
117
+ export default action('Write gasket config', writeGasketConfig);
@@ -0,0 +1,19 @@
1
+ import path from 'path';
2
+ import { writeFile } from 'fs/promises';
3
+ import action from '../action-wrapper.js';
4
+
5
+ /**
6
+ * Writes the contents of `pkg` to the app's package.json.
7
+ *
8
+ * @param {CreateContext} context - Create context
9
+ * @returns {Promise} promise
10
+ */
11
+ async function writePkg({ context }) {
12
+ const { dest, pkg, generatedFiles } = context;
13
+ const fileName = 'package.json';
14
+ const filePath = path.join(dest, fileName);
15
+ await writeFile(filePath, JSON.stringify(pkg, null, 2), 'utf8');
16
+ generatedFiles.add(fileName);
17
+ }
18
+
19
+ export default action('Write package.json', writePkg);