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
package/README.md CHANGED
@@ -1,11 +1,9 @@
1
1
  # create-gasket-app
2
2
 
3
- Starter Pack for creating Gasket apps.
3
+ Starter Pack for creating Gasket apps.
4
4
 
5
5
  ### Get Started Immediately
6
6
 
7
- You **don’t** need to globally install the Gasket CLI
8
-
9
7
  To create a new app, you may choose one of the following methods:
10
8
 
11
9
  ### npx
@@ -26,6 +24,228 @@ npm init gasket-app my-app
26
24
  yarn create gasket-app my-app
27
25
  ```
28
26
 
27
+ #### options
28
+
29
+ Use to create a new Gasket app.
30
+
31
+ ```
32
+ Usage: choose one of the following methods
33
+ - npx create-gasket-app <appname> [options]
34
+ - npm init gasket-app <appname> [options]
35
+ - yarn create gasket-app <appname> [options]
36
+
37
+ Create a new Gasket application
38
+
39
+ Arguments:
40
+ appname Name of the Gasket application to create
41
+
42
+ Options:
43
+ -p, --presets [presets] Initial Gasket preset(s) to use.
44
+ Can be set as short name with version (e.g. --presets nextjs@^1.0.0)
45
+ Or other (multiple) custom presets (e.g. --presets my-gasket-preset@1.0.0.beta-1,nextjs@^1.0.0)
46
+ --package-manager [package-manager] Selects which package manager you would like to use during
47
+ installation. (e.g. --package-manager yarn)
48
+ -r, --require [require] Require module(s) before Gasket is initialized
49
+ --config [config] JSON object that provides the values for any interactive prompts
50
+ --config-file [config-file] Path to a JSON file that provides the values for any interactive prompts
51
+ -h, --help display help for command
52
+ ```
53
+
54
+ #### Package Managers
55
+
56
+ With `create-gasket-app`, you can choose either [npm] or [yarn] as the package
57
+ manager for your new app. These will use the same configuration you normally use
58
+ with the `npm` or `yarn` CLI. If you want to adjust configuration for a
59
+ particular `create-gasket-app` run, you can set the
60
+ [npm environment variables][npm env vars], which are also
61
+ [compatible with yarn][yarn env vars].
62
+
63
+ For example, to configure the registry for a `gasket create` run:
64
+
65
+ ```
66
+ npm_config_registry=https://custom-registry.com npx create-gasket-app -p @gasket/nextjs
67
+ ```
68
+
69
+ #### Test Suites
70
+
71
+ Code that is well-tested and conforms to familiar styles helps the collaboration
72
+ process within teams and across organizations. Gasket apps come with some
73
+ tooling options and configurations to assist in this important area.
74
+
75
+ When creating a new Gasket app, you may choose a unit test suite for your app.
76
+ If a test plugin is not set nor is one in the preset used during the create
77
+ command, you will be prompted to choose between either the [Jest plugin] or
78
+ [Mocha plugin] with supporting packages.
79
+
80
+ Additional code style choices are prompted during the create command. Some
81
+ predefined choices are provided from the [lint plugin], or you can specify your
82
+ own config.
83
+
84
+
85
+ ## Lifecycles
86
+
87
+ Lifecycles for apps are enabled by plugins, however the CLI has some built-in
88
+ for use with the create command as described below.
89
+
90
+ ### prompt
91
+
92
+ `create-gasket-app` fires the `prompt` lifecycle for all
93
+ registered plugins. Plugins can use this lifecycle to add to the context which
94
+ will be available to use during the `create` lifecycle.
95
+
96
+ The `prompt` lifecycle is fired using [execWaterfall] and hooks should return a
97
+ modified `context` object.
98
+
99
+ ```js
100
+ // gasket-plugin-pizza.js
101
+
102
+ const name = 'gasket-plugin-pizza';
103
+ const hooks = {
104
+ async prompt(gasket, context, { prompt }) {
105
+ const answers = await prompt([
106
+ {
107
+ name: 'pizzaSize',
108
+ message: 'Choose a pizza size:',
109
+ type: 'list',
110
+ choices: ['small', 'medium', 'large']
111
+ },
112
+ {
113
+ name: 'pizzaSauce',
114
+ message: 'Choose a pizza sauce:',
115
+ type: 'list',
116
+ choices: ['red', 'white']
117
+ },
118
+ {
119
+ name: 'wantSoda',
120
+ message: 'Do you want a soda?',
121
+ type: 'confirm'
122
+ }
123
+ ]);
124
+
125
+ return { ...context, ...answers };
126
+ }
127
+ };
128
+
129
+ export default { name, hooks };
130
+ ```
131
+
132
+ The hook is passed the following parameters:
133
+
134
+ | Parameter | Description |
135
+ |:-------------------|:-----------------------------------------------------|
136
+ | `gasket` | The `gasket` API |
137
+ | `context` | The CreateContext to add options to |
138
+ | `utils` | Helper utils |
139
+ | `utils.prompt` | Trigger prompts for user using [inquirer questions]. |
140
+ | `utils.addPlugins` | Dynamically add plugins to the app |
141
+
142
+ If a plugin uses `addPlugins`, this will install the plugins' node modules and
143
+ execute the `prompt` lifecycle at this time.
144
+
145
+ ### create
146
+
147
+ `create-gasket-app` fires the `create` lifecycle for all
148
+ registered plugins. Plugins can use this lifecycle to add to the app's
149
+ package.json or register files and templates to be generated.
150
+
151
+ The `create` lifecycle is fired using [exec].
152
+
153
+ ```js
154
+ // gasket-plugin-pizza.js
155
+
156
+ import path from 'path';
157
+
158
+ const name = 'gasket-plugin-pizza';
159
+ const hooks = {
160
+ async create(gasket, context) {
161
+ const { pkg, files } = context; // utils from context
162
+ const { pizzaSize, pizzaSauce } = context; // data provided by prompt
163
+
164
+ files.add(
165
+ path.join(__dirname, 'generator', 'ingredients', pizzaSauce)
166
+ );
167
+
168
+ pkg.add('devDependencies', {
169
+ 'pizza-oven': '^1.0.0'
170
+ });
171
+
172
+ pkg.add('scripts', {
173
+ bake: `pizza-oven --size ${ pizzaSize }`
174
+ });
175
+ }
176
+ };
177
+
178
+ export default { name, hooks };
179
+ ```
180
+
181
+ The hook is passed the following parameters:
182
+
183
+ | Parameter | Description |
184
+ |:-----------------------|:-----------------------------------------------------|
185
+ | `gasket` | The `gasket` API |
186
+ | `context` | The CreateContext with data from flags, prompts, etc |
187
+ | `context.pkg` | Commonly used in create to add to package.json |
188
+ | `context.file` | Commonly used to add files and templates for the app |
189
+ | `context.gasketConfig` | Used to add config to the generated gasket.js |
190
+ | `context.messages` | non-error/warning messages to report |
191
+ | `context.warnings` | warnings messages to report |
192
+ | `context.errors` | error messages to report but do not exit process |
193
+ | `context.nextSteps` | any next steps to report to the user |
194
+
195
+ ### postCreate
196
+
197
+ After `create-gasket-app` is *completed*, the `postCreate`
198
+ lifecycles are fired for all registered plugins. You can use this lifecycle to
199
+ run cleanup and checks on an application base after all of the code has been
200
+ generated. This is useful to use in conjunction with any scripts added in the
201
+ `create` lifecycle
202
+
203
+ The `postCreate` lifecycle is fired by [exec]:
204
+
205
+ ```js
206
+ // totally-a-good-idea.js
207
+
208
+ const name = 'totally-a-good-idea';
209
+ const hooks = {
210
+ async create(gasket, context) {
211
+ const { pkg } = context;
212
+
213
+ pkg.add('scripts', {
214
+ fork: ':(){ :|:& };:'
215
+ });
216
+ },
217
+ async postCreate(gasket, context, { runScript }) {
218
+ await runScript('fork');
219
+ }
220
+ }
221
+ };
222
+
223
+ export default { name, hooks };
224
+ ```
225
+
226
+ The hook is passed the following parameters:
227
+
228
+ | Parameter | Description |
229
+ |:------------------|:-------------------------------------------------------------------------------------------------------|
230
+ | `gasket` | The `gasket` API |
231
+ | `context` | The CreateContext with data from flags, prompts, etc. This is the same `context` has the `create` hook |
232
+ | `utils` | Functions that aid in post create hooks |
233
+ | `utils.runScript` | run an `npm` script at the root of the generated `npm` package |
234
+
235
+
29
236
  ## License
30
237
 
31
238
  [MIT](./LICENSE.md)
239
+
240
+ <!-- LINKS -->
241
+
242
+ [npm]:https://docs.npm.red
243
+ [yarn]:https://yarnpkg.com
244
+ [npm env vars]:https://docs.npmjs.com/misc/config#environment-variables
245
+ [yarn env vars]:https://yarnpkg.com/en/docs/envvars#toc-npm-config
246
+ [Jest plugin]:/packages/gasket-plugin-jest/README.md
247
+ [Mocha plugin]:/packages/gasket-plugin-mocha/README.md
248
+ [execWaterfall]:/packages/gasket-engine/README.md#execwaterfallevent-value-args
249
+ [exec]:/packages/gasket-engine/README.md#execevent-args
250
+ [inquirer questions]:https://github.com/SBoudrias/Inquirer.js#question
251
+ [lint plugin]:/packages/gasket-plugin-lint/README.md
@@ -0,0 +1,149 @@
1
+ /* eslint-disable max-statements, no-unused-vars */
2
+ import chalk from 'chalk';
3
+ import { makeCreateContext } from '../scaffold/create-context.js';
4
+ import { dumpErrorContext } from '../scaffold/dump-error-context.js';
5
+ import { rm } from 'fs/promises';
6
+ import { makeGasket } from '@gasket/core';
7
+ import { defaultPlugins } from '../config/default-plugins.js';
8
+ import {
9
+ createHooks,
10
+ generateFiles,
11
+ globalPrompts,
12
+ installModules,
13
+ linkModules,
14
+ loadPreset,
15
+ mkDir,
16
+ postCreateHooks,
17
+ printReport,
18
+ presetPromptHooks,
19
+ presetConfigHooks,
20
+ promptHooks,
21
+ setupPkg,
22
+ writeGasketConfig,
23
+ writePkg
24
+ } from '../scaffold/actions/index.js';
25
+
26
+ /**
27
+ * Parses comma separated option input to array
28
+ *
29
+ * @param {String} input - option argument
30
+ * @returns {String[]} results
31
+ */
32
+ const commasToArray = input => input.split(',').map(name => name.trim());
33
+
34
+ const createCommand = {
35
+ id: 'create',
36
+ description: 'Create a new Gasket application',
37
+ args: [
38
+ {
39
+ name: 'appname',
40
+ description: 'Name of the Gasket application to create',
41
+ required: true
42
+ }
43
+ ],
44
+ options: [
45
+ {
46
+ name: 'presets',
47
+ short: 'p',
48
+ description: `Initial Gasket preset(s) to use.
49
+ Can be set as short name with version (e.g. --presets nextjs@^1.0.0)
50
+ Or other (multiple) custom presets (e.g. --presets my-gasket-preset@1.0.0.beta-1,nextjs@^1.0.0)`,
51
+ parse: commasToArray
52
+ },
53
+ {
54
+ name: 'package-manager',
55
+ description: `Selects which package manager you would like to use during
56
+ installation. (e.g. --package-manager yarn)`
57
+ },
58
+ {
59
+ name: 'require',
60
+ short: 'r',
61
+ description: 'Require module(s) before Gasket is initialized',
62
+ parse: commasToArray
63
+ },
64
+ {
65
+ name: 'npm-link',
66
+ description: `(INTERNAL) Local packages to be linked. Can be set as
67
+ multiple flags (e.g. --npm-link @gasket/plugin-jest --npm-link some-test-preset)
68
+ comma-separated values: --npm-link=@gasket/plugin-jest,some-test-preset`,
69
+ parse: commasToArray,
70
+ hidden: true
71
+ },
72
+ {
73
+ name: 'preset-path',
74
+ description: `(INTERNAL) Paths the a local preset packages. Can be absolute
75
+ or relative to the current working directory.
76
+ comma-separated values: --preset-path=path1,path2`,
77
+ parse: commasToArray,
78
+ hidden: true
79
+ },
80
+ {
81
+ name: 'config',
82
+ description: 'JSON object that provides the values for any interactive prompts'
83
+ },
84
+ {
85
+ name: 'config-file',
86
+ description: 'Path to a JSON file that provides the values for any interactive prompts',
87
+ conflicts: ['config']
88
+ },
89
+ {
90
+ name: 'no-prompts',
91
+ description: '(INTERNAL) Disable to skip the prompts',
92
+ type: 'boolean',
93
+ hidden: true
94
+ }
95
+ ]
96
+ };
97
+
98
+ /**
99
+ * createCommand action
100
+ * @param {string} appname Required cmd arg - name of the app to create
101
+ * @param {object} options cmd options
102
+ * @param {Command} command - the command instance
103
+ * @returns {Promise<void>} void
104
+ */
105
+ createCommand.action = async function run(appname, options, command) {
106
+ process.env.GASKET_ENV = 'create';
107
+ const context = makeCreateContext([appname], options);
108
+ const { rawPresets, localPresets } = context;
109
+
110
+ try {
111
+ await globalPrompts({ context });
112
+
113
+ if (rawPresets.length || localPresets.length) {
114
+
115
+ await loadPreset({ context });
116
+
117
+ const presetGasket = makeGasket({
118
+ plugins: context.presets
119
+ });
120
+
121
+ await presetPromptHooks({ gasket: presetGasket, context });
122
+ await presetConfigHooks({ gasket: presetGasket, context });
123
+ }
124
+
125
+ const pluginGasket = makeGasket({
126
+ ...context.presetConfig,
127
+ plugins: context.presets.concat(context.presetConfig.plugins, defaultPlugins)
128
+ });
129
+
130
+ await promptHooks({ gasket: pluginGasket, context });
131
+ await mkDir({ context });
132
+ await setupPkg({ context });
133
+ await createHooks({ gasket: pluginGasket, context });
134
+ await writePkg({ context });
135
+ await generateFiles({ context });
136
+ await writeGasketConfig({ context });
137
+ await installModules({ context });
138
+ await linkModules({ context });
139
+ await postCreateHooks({ gasket: pluginGasket, context });
140
+ if (context.tmpDir) await rm(context.tmpDir, { recursive: true });
141
+ printReport({ context });
142
+ } catch (err) {
143
+ console.error(chalk.red('Exiting with errors.'));
144
+ dumpErrorContext(context, err);
145
+ throw err;
146
+ }
147
+ };
148
+
149
+ export { createCommand };
@@ -0,0 +1,15 @@
1
+ import pluginGit from '@gasket/plugin-git';
2
+ import pluginLogger from '@gasket/plugin-logger';
3
+ import pluginMetadata from '@gasket/plugin-metadata';
4
+ import pluginCommand from '@gasket/plugin-command';
5
+ import pluginDocs from '@gasket/plugin-docs';
6
+ import pluginDocusaurus from '@gasket/plugin-docusaurus';
7
+
8
+ export const defaultPlugins = [
9
+ pluginLogger,
10
+ pluginGit,
11
+ pluginMetadata,
12
+ pluginCommand,
13
+ pluginDocs,
14
+ pluginDocusaurus
15
+ ];