create-gasket-app 7.4.18 → 8.0.0-next.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.
- package/EXAMPLES.md +5 -11
- package/README.md +4 -17
- package/lib/commands/create.js +6 -86
- package/lib/index.d.ts +0 -26
- package/lib/internal.d.ts +1 -5
- package/lib/scaffold/actions/global-prompts.js +0 -73
- package/lib/scaffold/actions/prompt-hooks.js +3 -3
- package/lib/scaffold/create-context.js +1 -12
- package/package.json +21 -13
- package/lib/scaffold/actions/load-preset.js +0 -89
- package/lib/scaffold/actions/preset-config-hooks.js +0 -12
- package/lib/scaffold/actions/preset-prompt-hooks.js +0 -16
package/EXAMPLES.md
CHANGED
|
@@ -7,23 +7,17 @@ This document provides working examples for interfaces and utilities from the `c
|
|
|
7
7
|
The main interface for `create-gasket-app` is the command line:
|
|
8
8
|
|
|
9
9
|
```bash
|
|
10
|
-
# Basic app creation
|
|
11
|
-
npx create-gasket-app@latest my-app
|
|
12
|
-
|
|
13
|
-
# With presets
|
|
14
|
-
npx create-gasket-app@latest my-app --presets @gasket/preset-nextjs
|
|
10
|
+
# Basic app creation with template
|
|
11
|
+
npx create-gasket-app@latest my-app --template @gasket/template-nextjs-pages
|
|
15
12
|
|
|
16
13
|
# With package manager selection
|
|
17
|
-
npx create-gasket-app@latest my-app --package-manager pnpm
|
|
14
|
+
npx create-gasket-app@latest my-app --template @gasket/template-nextjs-pages --package-manager pnpm
|
|
18
15
|
|
|
19
16
|
# With configuration
|
|
20
|
-
npx create-gasket-app@latest my-app --config '{"typescript": true}'
|
|
17
|
+
npx create-gasket-app@latest my-app --template @gasket/template-nextjs-pages --config '{"typescript": true}'
|
|
21
18
|
|
|
22
19
|
# With config file
|
|
23
|
-
npx create-gasket-app@latest my-app --config-file ./create-config.json
|
|
24
|
-
|
|
25
|
-
# Skip prompts (for CI)
|
|
26
|
-
npx create-gasket-app@latest my-app --presets @gasket/preset-nextjs --no-prompts
|
|
20
|
+
npx create-gasket-app@latest my-app --template @gasket/template-nextjs-pages --config-file ./create-config.json
|
|
27
21
|
```
|
|
28
22
|
|
|
29
23
|
## Templates
|
package/README.md
CHANGED
|
@@ -40,9 +40,6 @@ Arguments:
|
|
|
40
40
|
appname Name of the Gasket application to create
|
|
41
41
|
|
|
42
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
43
|
--template [template] Selects which template you would like to use during
|
|
47
44
|
installation. (e.g. --template @gasket/template-nextjs-pages-js)
|
|
48
45
|
--template-path [template-path] (INTERNAL) Path to a local template package. Can be absolute
|
|
@@ -57,7 +54,7 @@ Options:
|
|
|
57
54
|
|
|
58
55
|
#### Templates
|
|
59
56
|
|
|
60
|
-
Templates provide a complete Gasket application ready to use
|
|
57
|
+
Templates provide a complete Gasket application ready to use.
|
|
61
58
|
|
|
62
59
|
##### Using Templates
|
|
63
60
|
|
|
@@ -92,8 +89,7 @@ Templates are npm packages that follow this structure:
|
|
|
92
89
|
|
|
93
90
|
When using templates:
|
|
94
91
|
- The entire `template/` directory is copied to your new app
|
|
95
|
-
- Template dependencies are installed with `npm ci`
|
|
96
|
-
- No preset processing or plugin creation flows are run
|
|
92
|
+
- Template dependencies are installed with `npm ci`
|
|
97
93
|
|
|
98
94
|
**Note:** Templates currently require npm as they come with `package-lock.json` files.
|
|
99
95
|
|
|
@@ -118,14 +114,8 @@ Code that is well-tested and conforms to familiar styles helps the collaboration
|
|
|
118
114
|
process within teams and across organizations. Gasket apps come with some
|
|
119
115
|
tooling options and configurations to assist in this important area.
|
|
120
116
|
|
|
121
|
-
When creating a new Gasket app, you
|
|
122
|
-
|
|
123
|
-
command, you will be prompted to choose between either the [Jest plugin] or
|
|
124
|
-
[Mocha plugin] with supporting packages.
|
|
125
|
-
|
|
126
|
-
Additional code style choices are prompted during the create command. Some
|
|
127
|
-
predefined choices are provided from the [lint plugin], or you can specify your
|
|
128
|
-
own config.
|
|
117
|
+
When creating a new Gasket app, you can configure your own test suite and
|
|
118
|
+
linting setup according to your team's preferences.
|
|
129
119
|
|
|
130
120
|
## Lifecycles
|
|
131
121
|
|
|
@@ -287,9 +277,6 @@ The hook is passed the following parameters:
|
|
|
287
277
|
[yarn]:https://yarnpkg.com
|
|
288
278
|
[npm env vars]:https://docs.npmjs.com/misc/config#environment-variables
|
|
289
279
|
[yarn env vars]:https://yarnpkg.com/en/docs/envvars#toc-npm-config
|
|
290
|
-
[Jest plugin]:/packages/gasket-plugin-jest/README.md
|
|
291
|
-
[Mocha plugin]:/packages/gasket-plugin-mocha/README.md
|
|
292
280
|
[execWaterfall]:/packages/gasket-core/docs/gasket-engine.md#execwaterfallevent-value-args
|
|
293
281
|
[exec]:/packages/gasket-core/docs/gasket-engine.md#execevent-args
|
|
294
282
|
[inquirer questions]:https://github.com/SBoudrias/Inquirer.js#question
|
|
295
|
-
[lint plugin]:/packages/gasket-plugin-lint/README.md
|
package/lib/commands/create.js
CHANGED
|
@@ -1,27 +1,11 @@
|
|
|
1
|
-
/* eslint-disable max-statements, no-unused-vars */
|
|
2
1
|
import chalk from 'chalk';
|
|
3
2
|
import { makeCreateContext } from '../scaffold/create-context.js';
|
|
4
3
|
import { dumpErrorContext } from '../scaffold/dump-error-context.js';
|
|
5
|
-
import { rm } from 'fs/promises';
|
|
6
|
-
import { makeGasket } from '@gasket/core';
|
|
7
|
-
import globalPrompts from '../scaffold/actions/global-prompts.js';
|
|
8
|
-
import loadPreset from '../scaffold/actions/load-preset.js';
|
|
9
4
|
import loadTemplate from '../scaffold/actions/load-template.js';
|
|
10
5
|
import copyTemplate from '../scaffold/actions/copy-template.js';
|
|
11
6
|
import customizeTemplate from '../scaffold/actions/customize-template.js';
|
|
12
7
|
import installTemplateDep from '../scaffold/actions/install-template-deps.js';
|
|
13
|
-
import presetPromptHooks from '../scaffold/actions/preset-prompt-hooks.js';
|
|
14
|
-
import presetConfigHooks from '../scaffold/actions/preset-config-hooks.js';
|
|
15
|
-
import promptHooks from '../scaffold/actions/prompt-hooks.js';
|
|
16
8
|
import mkDir from '../scaffold/actions/mkdir.js';
|
|
17
|
-
import setupPkg from '../scaffold/actions/setup-pkg.js';
|
|
18
|
-
import createHooks from '../scaffold/actions/create-hooks.js';
|
|
19
|
-
import writePkg from '../scaffold/actions/write-pkg.js';
|
|
20
|
-
import generateFiles from '../scaffold/actions/generate-files.js';
|
|
21
|
-
import writeGasketConfig from '../scaffold/actions/write-gasket-config.js';
|
|
22
|
-
import installModules from '../scaffold/actions/install-modules.js';
|
|
23
|
-
import linkModules from '../scaffold/actions/link-modules.js';
|
|
24
|
-
import postCreateHooks from '../scaffold/actions/post-create-hooks.js';
|
|
25
9
|
import printReport from '../scaffold/actions/print-report.js';
|
|
26
10
|
import gitInit from '../scaffold/actions/git-init.js';
|
|
27
11
|
|
|
@@ -42,14 +26,6 @@ const createCommand = {
|
|
|
42
26
|
}
|
|
43
27
|
],
|
|
44
28
|
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
29
|
{
|
|
54
30
|
name: 'template',
|
|
55
31
|
description: `Selects which template you would like to use during
|
|
@@ -75,16 +51,8 @@ const createCommand = {
|
|
|
75
51
|
{
|
|
76
52
|
name: 'npm-link',
|
|
77
53
|
description: `(INTERNAL) Local packages to be linked. Can be set as
|
|
78
|
-
multiple flags (e.g. --npm-link @gasket/plugin-jest
|
|
79
|
-
comma-separated values: --npm-link=@gasket/plugin-jest,some-test-
|
|
80
|
-
parse: commasToArray,
|
|
81
|
-
hidden: true
|
|
82
|
-
},
|
|
83
|
-
{
|
|
84
|
-
name: 'preset-path',
|
|
85
|
-
description: `(INTERNAL) Paths the a local preset packages. Can be absolute
|
|
86
|
-
or relative to the current working directory.
|
|
87
|
-
comma-separated values: --preset-path=path1,path2`,
|
|
54
|
+
multiple flags (e.g. --npm-link @gasket/plugin-jest)
|
|
55
|
+
comma-separated values: --npm-link=@gasket/plugin-jest,some-test-package`,
|
|
88
56
|
parse: commasToArray,
|
|
89
57
|
hidden: true
|
|
90
58
|
},
|
|
@@ -112,10 +80,10 @@ const createCommand = {
|
|
|
112
80
|
* @returns {import('../internal.js').PartialCreateContext} Validated context
|
|
113
81
|
*/
|
|
114
82
|
function validateOptions(context) {
|
|
115
|
-
const hasOption = (context) => Boolean(context.template || context.templatePath
|
|
83
|
+
const hasOption = (context) => Boolean(context.template || context.templatePath);
|
|
116
84
|
|
|
117
85
|
if (!hasOption(context)) {
|
|
118
|
-
console.warn('Warning: At least one of the options is required: --template, --template-path
|
|
86
|
+
console.warn('Warning: At least one of the options is required: --template, --template-path');
|
|
119
87
|
process.exit(1);
|
|
120
88
|
}
|
|
121
89
|
|
|
@@ -138,59 +106,11 @@ async function handleTemplate(context) {
|
|
|
138
106
|
return;
|
|
139
107
|
}
|
|
140
108
|
|
|
141
|
-
/**
|
|
142
|
-
* handlePresets - Handles the preset creation
|
|
143
|
-
* @param {import('../internal.js').PartialCreateContext} context - Create context
|
|
144
|
-
* @returns {Promise<void>} Promise that resolves when presets are applied
|
|
145
|
-
*/
|
|
146
|
-
async function handlePresets(context) {
|
|
147
|
-
await loadPreset({ context });
|
|
148
|
-
await globalPrompts({ context });
|
|
149
|
-
|
|
150
|
-
const presetGasket = makeGasket({
|
|
151
|
-
plugins: context.presets
|
|
152
|
-
});
|
|
153
|
-
|
|
154
|
-
await presetPromptHooks({ gasket: presetGasket, context });
|
|
155
|
-
await presetConfigHooks({ gasket: presetGasket, context });
|
|
156
|
-
|
|
157
|
-
const pluginGasket = makeGasket({
|
|
158
|
-
...context.presetConfig,
|
|
159
|
-
plugins: context.presetConfig.plugins.concat(context.presets)
|
|
160
|
-
});
|
|
161
|
-
|
|
162
|
-
await promptHooks({ gasket: pluginGasket, context });
|
|
163
|
-
await mkDir({ context });
|
|
164
|
-
await setupPkg({ context });
|
|
165
|
-
await createHooks({ gasket: pluginGasket, context });
|
|
166
|
-
await writePkg({ context });
|
|
167
|
-
await generateFiles({ context });
|
|
168
|
-
await writeGasketConfig({ context });
|
|
169
|
-
await installModules({ context });
|
|
170
|
-
await linkModules({ context });
|
|
171
|
-
await postCreateHooks({ gasket: pluginGasket, context });
|
|
172
|
-
if (context.tmpDir) await rm(context.tmpDir, { recursive: true });
|
|
173
|
-
printReport({ context });
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
/**
|
|
177
|
-
* handleCreate - Handles the create creation
|
|
178
|
-
* @param {import('../internal.js').PartialCreateContext} context - Create context
|
|
179
|
-
* @returns {Promise<void>} Promise that resolves when app is created
|
|
180
|
-
*/
|
|
181
|
-
async function handleCreate(context) {
|
|
182
|
-
const { template, templatePath } = context;
|
|
183
|
-
if (template || templatePath) {
|
|
184
|
-
await handleTemplate(context);
|
|
185
|
-
} else {
|
|
186
|
-
await handlePresets(context);
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
|
|
190
109
|
/**
|
|
191
110
|
* createCommand action
|
|
192
111
|
* @type {import('../index.js').createCommandAction}
|
|
193
112
|
*/
|
|
113
|
+
// eslint-disable-next-line no-unused-vars
|
|
194
114
|
createCommand.action = async function run(appname, options, command) {
|
|
195
115
|
// eslint-disable-next-line no-process-env
|
|
196
116
|
process.env.GASKET_ENV = 'create';
|
|
@@ -198,7 +118,7 @@ createCommand.action = async function run(appname, options, command) {
|
|
|
198
118
|
validateOptions(context);
|
|
199
119
|
|
|
200
120
|
try {
|
|
201
|
-
await
|
|
121
|
+
await handleTemplate(context);
|
|
202
122
|
} catch (err) {
|
|
203
123
|
console.error(chalk.red('Exiting with errors.'));
|
|
204
124
|
dumpErrorContext(context, err);
|
package/lib/index.d.ts
CHANGED
|
@@ -46,11 +46,9 @@ interface CommandOption {
|
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
export interface CreateCommandOptions {
|
|
49
|
-
presets?: string[];
|
|
50
49
|
template?: string;
|
|
51
50
|
templatePath?: string;
|
|
52
51
|
npmLink?: string[];
|
|
53
|
-
presetPath?: string[];
|
|
54
52
|
packageManager?: string;
|
|
55
53
|
prompts?: boolean;
|
|
56
54
|
config?: string;
|
|
@@ -81,8 +79,6 @@ export interface ModuleInfo {
|
|
|
81
79
|
version?: string;
|
|
82
80
|
}
|
|
83
81
|
|
|
84
|
-
export interface PresetInfo extends ModuleInfo { }
|
|
85
|
-
|
|
86
82
|
export interface PluginInfo extends ModuleInfo { }
|
|
87
83
|
|
|
88
84
|
export interface ConfigBuilder<Config> {
|
|
@@ -425,15 +421,6 @@ export interface CreateContext {
|
|
|
425
421
|
/** Whether or not target directory already exists */
|
|
426
422
|
extant: boolean;
|
|
427
423
|
|
|
428
|
-
/** paths to the local presets packages */
|
|
429
|
-
localPresets: Array<string>;
|
|
430
|
-
|
|
431
|
-
/**
|
|
432
|
-
* Raw preset desc from args. Can include version constraint. Added by
|
|
433
|
-
* load-preset if using localPresets.
|
|
434
|
-
*/
|
|
435
|
-
rawPresets: Array<string>;
|
|
436
|
-
|
|
437
424
|
/** Local packages that should be linked */
|
|
438
425
|
pkgLinks: Array<string>;
|
|
439
426
|
|
|
@@ -455,9 +442,6 @@ export interface CreateContext {
|
|
|
455
442
|
/** (INTERNAL) false to skip the prompts */
|
|
456
443
|
prompts: boolean;
|
|
457
444
|
|
|
458
|
-
/** Default empty array, populated by load-preset with actual imports */
|
|
459
|
-
presets: Array<Plugin>;
|
|
460
|
-
|
|
461
445
|
/** temporary directory */
|
|
462
446
|
tmpDir: string;
|
|
463
447
|
|
|
@@ -473,9 +457,6 @@ export interface CreateContext {
|
|
|
473
457
|
/** resolved template name for display */
|
|
474
458
|
templateName?: string;
|
|
475
459
|
|
|
476
|
-
/** Default to object w/empty plugins array to be populated by `presetConfig` hook */
|
|
477
|
-
presetConfig: GasketConfigDefinition;
|
|
478
|
-
|
|
479
460
|
// Added by `global-prompts`
|
|
480
461
|
|
|
481
462
|
/** Description of app */
|
|
@@ -538,13 +519,6 @@ export interface ActionWrapperParams {
|
|
|
538
519
|
declare module '@gasket/core' {
|
|
539
520
|
|
|
540
521
|
export interface HookExecTypes {
|
|
541
|
-
presetPrompt(
|
|
542
|
-
context: CreateContext,
|
|
543
|
-
utils: {
|
|
544
|
-
prompt: CreatePrompt;
|
|
545
|
-
}
|
|
546
|
-
): Promise<void>;
|
|
547
|
-
presetConfig(context: CreateContext): Promise<CreateContext['presetConfig']>;
|
|
548
522
|
prompt(
|
|
549
523
|
context: CreateContext,
|
|
550
524
|
utils: {
|
package/lib/internal.d.ts
CHANGED
|
@@ -103,10 +103,7 @@ export function promptForTestPlugin(
|
|
|
103
103
|
): Promise<string | null>;
|
|
104
104
|
export function allowExtantOverwriting(context: PartialCreateContext, prompt: CreatePrompt): Promise<void>;
|
|
105
105
|
export function globalPrompts(params: { context: PartialCreateContext }): Promise<void>;
|
|
106
|
-
export function loadPresets(params: { context: PartialCreateContext }): Promise<void>;
|
|
107
106
|
|
|
108
|
-
export function presetPromptHooks(params: { gasket?: Gasket; context: PartialCreateContext }): Promise<void>;
|
|
109
|
-
export function presetConfigHooks(params: { gasket?: Gasket; context: PartialCreateContext }): Promise<void>;
|
|
110
107
|
export function promptHooks(params: { gasket?: Gasket; context: PartialCreateContext }): Promise<void>;
|
|
111
108
|
export function execPluginPrompts(gasket: Gasket, context: PartialCreateContext): Promise<void>;
|
|
112
109
|
|
|
@@ -133,8 +130,7 @@ export function customizeTemplate(params: { context: PartialCreateContext }): Pr
|
|
|
133
130
|
export function installTemplateDeps(params: { context: PartialCreateContext }): Promise<void>;
|
|
134
131
|
export function gitInit(params: { context: PartialCreateContext }): Promise<void>;
|
|
135
132
|
|
|
136
|
-
|
|
137
|
-
/** Presets */
|
|
133
|
+
/** File Generation */
|
|
138
134
|
export function generateFiles({ context, spinner }: { context: CreateContext, spinner: Ora }): Promise<void>;
|
|
139
135
|
export function performGenerate(context: CreateContext, descriptors: Descriptior[]): boolean[];
|
|
140
136
|
export function getDescriptors(context: CreateContext): Promise<Descriptior[]>;
|
|
@@ -54,78 +54,6 @@ async function choosePackageManager(context, prompt) {
|
|
|
54
54
|
});
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
-
/**
|
|
58
|
-
* Choose your unit test suite and integration test suite
|
|
59
|
-
* @type {import('../../internal.js').chooseTestPlugins}
|
|
60
|
-
*/
|
|
61
|
-
async function chooseTestPlugins(context, prompt) {
|
|
62
|
-
const knownTestPlugins = {
|
|
63
|
-
unit: {
|
|
64
|
-
jest: '@gasket/plugin-jest',
|
|
65
|
-
mocha: '@gasket/plugin-mocha',
|
|
66
|
-
vitest: '@gasket/plugin-vitest'
|
|
67
|
-
},
|
|
68
|
-
integration: {
|
|
69
|
-
cypress: '@gasket/plugin-cypress'
|
|
70
|
-
}
|
|
71
|
-
};
|
|
72
|
-
|
|
73
|
-
const testTypes = ['unit', 'integration'];
|
|
74
|
-
const testPlugins = [];
|
|
75
|
-
|
|
76
|
-
const testPromptOptions = {
|
|
77
|
-
unit: {
|
|
78
|
-
name: 'Vitest',
|
|
79
|
-
plugin: '@gasket/plugin-vitest',
|
|
80
|
-
isDefault: true
|
|
81
|
-
},
|
|
82
|
-
integration: {
|
|
83
|
-
name: 'Cypress',
|
|
84
|
-
plugin: '@gasket/plugin-cypress',
|
|
85
|
-
isDefault: false
|
|
86
|
-
}
|
|
87
|
-
};
|
|
88
|
-
|
|
89
|
-
if (!('testPlugins' in context)) {
|
|
90
|
-
for (const type of testTypes) {
|
|
91
|
-
if (type + 'TestSuite' in context) {
|
|
92
|
-
const testSuite = knownTestPlugins[type][context[type + 'TestSuite']];
|
|
93
|
-
if (testSuite) testPlugins.push(testSuite);
|
|
94
|
-
} else {
|
|
95
|
-
const { name, isDefault, plugin: testPlugin } = testPromptOptions[type];
|
|
96
|
-
const plugin = await promptForTestPlugin(
|
|
97
|
-
prompt,
|
|
98
|
-
`Do you want to use ${name} for ${type} testing?`,
|
|
99
|
-
isDefault
|
|
100
|
-
);
|
|
101
|
-
|
|
102
|
-
if (plugin) testPlugins.push(testPlugin);
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
if (testPlugins.length > 0) {
|
|
107
|
-
Object.assign(context, { testPlugins });
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
/**
|
|
113
|
-
*
|
|
114
|
-
* @type {import('../../internal.js').promptForTestPlugin}
|
|
115
|
-
*/
|
|
116
|
-
async function promptForTestPlugin(prompt, message, isDefault) {
|
|
117
|
-
const { testPlugin } = await prompt([
|
|
118
|
-
{
|
|
119
|
-
name: 'testPlugin',
|
|
120
|
-
message,
|
|
121
|
-
type: 'confirm',
|
|
122
|
-
default: isDefault
|
|
123
|
-
}
|
|
124
|
-
]);
|
|
125
|
-
|
|
126
|
-
return testPlugin !== 'none' ? testPlugin : null;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
57
|
/**
|
|
130
58
|
* Given that gasket is creating in an already existing directory, it should
|
|
131
59
|
* confirm with the user that it's intentionally overwriting that directory
|
|
@@ -150,7 +78,6 @@ async function allowExtantOverwriting(context, prompt) {
|
|
|
150
78
|
export const questions = [
|
|
151
79
|
chooseAppDescription,
|
|
152
80
|
choosePackageManager,
|
|
153
|
-
chooseTestPlugins,
|
|
154
81
|
allowExtantOverwriting
|
|
155
82
|
];
|
|
156
83
|
|
|
@@ -2,7 +2,7 @@ import inquirer from 'inquirer';
|
|
|
2
2
|
import { withGasketSpinner } from '../with-spinner.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
* Initializes engine with
|
|
5
|
+
* Initializes engine with provided plugins
|
|
6
6
|
* to execute their prompt lifecycle hooks.
|
|
7
7
|
* @type {import('../../internal.js').execPluginPrompts}
|
|
8
8
|
*/
|
|
@@ -25,8 +25,8 @@ async function execPluginPrompts(gasket, context) {
|
|
|
25
25
|
*/
|
|
26
26
|
async function promptHooks({ gasket, context }) {
|
|
27
27
|
//
|
|
28
|
-
// Because `execPluginPrompts` is
|
|
29
|
-
// with the processPlugins
|
|
28
|
+
// Because `execPluginPrompts` is recursive, we need to start it
|
|
29
|
+
// with the processPlugins from our initial context
|
|
30
30
|
//
|
|
31
31
|
await execPluginPrompts(gasket, context);
|
|
32
32
|
}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
/* eslint-disable max-statements */
|
|
2
1
|
import fs from 'fs';
|
|
3
2
|
import path from 'path';
|
|
4
3
|
import { readConfig } from '../scaffold/utils.js';
|
|
@@ -73,21 +72,17 @@ export class CreateContext {
|
|
|
73
72
|
export function makeCreateContext(argv = [], options = {}) {
|
|
74
73
|
const appName = argv[0] || 'templated-app';
|
|
75
74
|
const {
|
|
76
|
-
presets = [],
|
|
77
75
|
template,
|
|
78
76
|
templatePath,
|
|
79
77
|
npmLink = [],
|
|
80
|
-
presetPath = [],
|
|
81
78
|
packageManager,
|
|
82
79
|
prompts,
|
|
83
80
|
config,
|
|
84
81
|
configFile
|
|
85
82
|
} = options;
|
|
86
83
|
|
|
87
|
-
// Flatten the array of array created by the plugins flag –
|
|
84
|
+
// Flatten the array of array created by the plugins flag – it
|
|
88
85
|
// supports both multiple instances as well as comma-separated lists.
|
|
89
|
-
const rawPresets = presets.reduce(flatten, []);
|
|
90
|
-
const localPresets = presetPath.reduce(flatten, []);
|
|
91
86
|
const pkgLinks = npmLink.reduce(flatten, []);
|
|
92
87
|
const cwd = process.cwd();
|
|
93
88
|
const dest = path.join(cwd, appName);
|
|
@@ -107,8 +102,6 @@ export function makeCreateContext(argv = [], options = {}) {
|
|
|
107
102
|
relDest,
|
|
108
103
|
extant,
|
|
109
104
|
pkgLinks,
|
|
110
|
-
localPresets,
|
|
111
|
-
rawPresets,
|
|
112
105
|
template,
|
|
113
106
|
templatePath,
|
|
114
107
|
messages: [],
|
|
@@ -117,10 +110,6 @@ export function makeCreateContext(argv = [], options = {}) {
|
|
|
117
110
|
nextSteps: [],
|
|
118
111
|
generatedFiles: new Set(),
|
|
119
112
|
prompts,
|
|
120
|
-
presets: [],
|
|
121
|
-
presetConfig: {
|
|
122
|
-
plugins: []
|
|
123
|
-
},
|
|
124
113
|
readme: []
|
|
125
114
|
});
|
|
126
115
|
|
package/package.json
CHANGED
|
@@ -1,17 +1,26 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-gasket-app",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "8.0.0-next.1",
|
|
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
9
|
"types": "lib/index.d.ts",
|
|
11
10
|
"files": [
|
|
12
11
|
"lib",
|
|
13
12
|
"EXAMPLES.md"
|
|
14
13
|
],
|
|
14
|
+
"exports": {
|
|
15
|
+
".": {
|
|
16
|
+
"types": "./lib/index.d.ts",
|
|
17
|
+
"import": "./lib/index.js"
|
|
18
|
+
},
|
|
19
|
+
"./lib/internal.d.ts": {
|
|
20
|
+
"types": "./lib/internal.d.ts"
|
|
21
|
+
},
|
|
22
|
+
"./package.json": "./package.json"
|
|
23
|
+
},
|
|
15
24
|
"repository": "godaddy/gasket.git",
|
|
16
25
|
"publishConfig": {
|
|
17
26
|
"access": "public"
|
|
@@ -32,23 +41,22 @@
|
|
|
32
41
|
"mkdirp": "^1.0.4",
|
|
33
42
|
"ora": "^3.4.0",
|
|
34
43
|
"semver": "^7.7.1",
|
|
35
|
-
"@gasket/
|
|
36
|
-
"@gasket/plugin-
|
|
37
|
-
"@gasket/plugin-
|
|
38
|
-
"@gasket/plugin-
|
|
39
|
-
"@gasket/plugin-
|
|
40
|
-
"@gasket/plugin-logger": "^
|
|
41
|
-
"@gasket/plugin-metadata": "^
|
|
42
|
-
"@gasket/request": "^
|
|
43
|
-
"@gasket/utils": "^
|
|
44
|
-
"@gasket/core": "^7.7.2"
|
|
44
|
+
"@gasket/core": "^8.0.0-next.1",
|
|
45
|
+
"@gasket/plugin-command": "^8.0.0-next.1",
|
|
46
|
+
"@gasket/plugin-docs": "^8.0.0-next.1",
|
|
47
|
+
"@gasket/plugin-docusaurus": "^8.0.0-next.1",
|
|
48
|
+
"@gasket/plugin-dynamic-plugins": "^8.0.0-next.1",
|
|
49
|
+
"@gasket/plugin-logger": "^8.0.0-next.1",
|
|
50
|
+
"@gasket/plugin-metadata": "^8.0.0-next.1",
|
|
51
|
+
"@gasket/request": "^8.0.0-next.1",
|
|
52
|
+
"@gasket/utils": "^8.0.0-next.1"
|
|
45
53
|
},
|
|
46
54
|
"devDependencies": {
|
|
47
55
|
"@typescript-eslint/parser": "^8.38.0",
|
|
48
56
|
"@vitest/coverage-v8": "^3.2.0",
|
|
49
57
|
"dotenv": "^16.4.7",
|
|
50
58
|
"vitest": "^3.2.0",
|
|
51
|
-
"@gasket/request": "^
|
|
59
|
+
"@gasket/request": "^8.0.0-next.1"
|
|
52
60
|
},
|
|
53
61
|
"scripts": {
|
|
54
62
|
"lint": "eslint .",
|
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
import path from 'path';
|
|
2
|
-
import os from 'os';
|
|
3
|
-
import { withSpinner } from '../with-spinner.js';
|
|
4
|
-
import { PackageManager } from '@gasket/utils';
|
|
5
|
-
import { mkdtemp } from 'fs/promises';
|
|
6
|
-
import { createRequire } from 'module';
|
|
7
|
-
import { pathToFileURL } from 'url';
|
|
8
|
-
|
|
9
|
-
const require = createRequire(import.meta.url);
|
|
10
|
-
const hasVersionOrTag = /@([\^~]?\d+\.\d+\.\d+(?:-[\d\w.-]+)?|[\^~]?\d+\.\d+\.\d+|[a-zA-Z]+|file:.+)$/;
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* validatePresetName - Validate the preset name
|
|
14
|
-
* @param {string} preset - The preset name
|
|
15
|
-
* @returns {void}
|
|
16
|
-
*/
|
|
17
|
-
function validatePresetName(preset) {
|
|
18
|
-
const isNotShortName = preset.includes('/gasket-preset-') || preset.includes('@gasket/preset-');
|
|
19
|
-
const isMispelled = preset.endsWith('-preset');
|
|
20
|
-
|
|
21
|
-
if (isMispelled) {
|
|
22
|
-
throw new Error(`Invalid preset name: ${preset}. Please check the name and try again.`);
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
if (!isNotShortName) {
|
|
26
|
-
throw new Error(`Invalid preset short name: ${preset}. Presets must be a full name.`);
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* loadPresets - Load presets to temp directory
|
|
32
|
-
* @type {import('../../internal.js').loadPresets}
|
|
33
|
-
*/
|
|
34
|
-
async function loadPresets({ context }) {
|
|
35
|
-
const tmpDir = await mkdtemp(path.join(os.tmpdir(), `gasket-create-${context.appName}`));
|
|
36
|
-
context.tmpDir = tmpDir;
|
|
37
|
-
|
|
38
|
-
const modPath = path.join(tmpDir, 'node_modules');
|
|
39
|
-
const pkgManager = new PackageManager({
|
|
40
|
-
packageManager: context.packageManager,
|
|
41
|
-
dest: tmpDir
|
|
42
|
-
});
|
|
43
|
-
const pkgVerb = pkgManager.manager === 'npm' ? 'install' : 'add';
|
|
44
|
-
|
|
45
|
-
const remotePresets = context.rawPresets.map(async preset => {
|
|
46
|
-
validatePresetName(preset);
|
|
47
|
-
const parts = hasVersionOrTag.test(preset) && preset.split('@').filter(Boolean);
|
|
48
|
-
const name = parts ? `@${parts[0]}` : preset;
|
|
49
|
-
const version = parts ? `@${parts[1]}` : '@latest';
|
|
50
|
-
|
|
51
|
-
try {
|
|
52
|
-
// Install the preset
|
|
53
|
-
await pkgManager.exec(pkgVerb, [`${name}${version}`]);
|
|
54
|
-
// Get the package file
|
|
55
|
-
const pkgFile = require(path.join(modPath, name, 'package.json'));
|
|
56
|
-
// Import the preset via the package file attrs, name and main
|
|
57
|
-
// We can't specify the cwd for the import, so we need to use the full path
|
|
58
|
-
// expects type:module & "main": "lib/fullpath.js"
|
|
59
|
-
const entryPath = pkgFile.main ?? pkgFile.exports['.'].import ?? pkgFile.exports['.'].default;
|
|
60
|
-
const fullPath = path.resolve(modPath, name, entryPath);
|
|
61
|
-
const mod = await import(pathToFileURL(fullPath).href);
|
|
62
|
-
return mod.default?.default || mod.default || mod;
|
|
63
|
-
} catch (err) {
|
|
64
|
-
const errorMessage = err.stderr || err.message;
|
|
65
|
-
if (err.stderr && err.stderr.includes('is not in this registry')) {
|
|
66
|
-
throw new Error(`Preset not found in registry: ${name}${version}. Use npm_config_registry=<registry> to use privately scoped presets.`);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
throw new Error(`Failed to install preset ${name}${version}: ${errorMessage}`);
|
|
70
|
-
}
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
const localPresets = context.localPresets.map(async localPresetPath => {
|
|
74
|
-
try {
|
|
75
|
-
await pkgManager.exec(pkgVerb, [localPresetPath]);
|
|
76
|
-
const pkgFile = require(path.join(localPresetPath, 'package.json'));
|
|
77
|
-
const entryPath = pkgFile.main ?? pkgFile.exports['.'].import ?? pkgFile.exports['.'].default;
|
|
78
|
-
const fullPath = path.resolve(modPath, pkgFile.name, entryPath);
|
|
79
|
-
const mod = await import(pathToFileURL(fullPath).href);
|
|
80
|
-
return mod.default?.default || mod.default || mod;
|
|
81
|
-
} catch {
|
|
82
|
-
throw new Error(`Failed to install local preset ${localPresetPath}`);
|
|
83
|
-
}
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
context.presets = await Promise.all([...remotePresets, ...localPresets]);
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
export default withSpinner('Load presets', loadPresets);
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { withGasketSpinner } from '../with-spinner.js';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* presetConfigHooks - exec `presetConfig` hook
|
|
5
|
-
* @type {import('../../internal.js').presetConfigHooks}
|
|
6
|
-
*/
|
|
7
|
-
async function presetConfigHooks({ gasket, context }) {
|
|
8
|
-
const config = await gasket.execWaterfall('presetConfig', context);
|
|
9
|
-
Object.assign(context.presetConfig, config);
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export default withGasketSpinner('Preset Config', presetConfigHooks, { startSpinner: false });
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import inquirer from 'inquirer';
|
|
2
|
-
import { withGasketSpinner } from '../with-spinner.js';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* presetPromptHooks - exec `presetPrompt` hook
|
|
6
|
-
* @type {import('../../internal.js').presetPromptHooks}
|
|
7
|
-
*/
|
|
8
|
-
async function presetPromptHooks({ gasket, context }) {
|
|
9
|
-
const prompt = context.prompts ? inquirer.createPromptModule() : () => ({});
|
|
10
|
-
|
|
11
|
-
const nextContext = await gasket.execWaterfall('presetPrompt', context, { prompt });
|
|
12
|
-
|
|
13
|
-
Object.assign(context, nextContext);
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export default withGasketSpinner('Preset prompts', presetPromptHooks, { startSpinner: false });
|