create-gasket-app 7.4.17 → 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 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, unlike presets which build apps through a plugin-based creation process.
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 may choose a unit test suite for your app.
122
- If a test plugin is not set nor is one in the preset used during the create
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
@@ -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 --npm-link some-test-preset)
79
- comma-separated values: --npm-link=@gasket/plugin-jest,some-test-preset`,
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 || context.rawPresets.length || context.localPresets.length);
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, --presets, --preset-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 handleCreate(context);
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[]>;
@@ -1,52 +1,35 @@
1
1
  import path from 'path';
2
2
  import { withSpinner } from '../with-spinner.js';
3
- import { cp, readdir, writeFile, access } from 'fs/promises';
3
+ import { cp, readdir, rename } from 'fs/promises';
4
4
 
5
5
  const EXCLUDED_FILES = ['node_modules'];
6
+ const TEMPLATE_SUFFIX = '.template';
6
7
 
7
8
  /**
8
- * Ensures a .gitignore exists in the generated app.
9
- * npm intentionally strips .gitignore files from published packages.
10
- * We will need to update our templates to use a different name
11
- * such as gitignore or .gitignore.template to survive installing.
12
- * @param {import("../../internal.d.ts").PartialCreateContext} context - Create context
13
- * @returns {Promise<void>}
9
+ * Recursively processes .template files in a directory,
10
+ * renaming them to remove the .template suffix.
11
+ * @param {string} dir - Directory to process
12
+ * @returns {Promise<string[]>} - List of renamed files (destination paths)
14
13
  */
15
- export async function ensureGitignore(context) {
16
- const destPath = path.join(context.dest, '.gitignore');
17
-
18
- const exists = await access(destPath)
19
- .then(() => true)
20
- .catch(() => false);
21
-
22
- if (exists) {
23
- return;
24
- }
25
-
26
- const npmignorePath = path.join(context.dest, '.npmignore');
27
- try {
28
- await cp(npmignorePath, destPath);
29
- context.generatedFiles.add(path.relative(context.cwd, destPath));
30
- return;
31
- } catch (err) {
32
- if (err.code !== 'ENOENT') throw err;
14
+ async function processTemplateFiles(dir) {
15
+ const renamedFiles = [];
16
+ const entries = await readdir(dir, { withFileTypes: true });
17
+
18
+ for (const entry of entries) {
19
+ const fullPath = path.join(dir, entry.name);
20
+
21
+ if (entry.isDirectory()) {
22
+ const nested = await processTemplateFiles(fullPath);
23
+ renamedFiles.push(...nested);
24
+ } else if (entry.name.endsWith(TEMPLATE_SUFFIX)) {
25
+ const newName = entry.name.slice(0, -TEMPLATE_SUFFIX.length);
26
+ const newPath = path.join(dir, newName);
27
+ await rename(fullPath, newPath);
28
+ renamedFiles.push(newPath);
29
+ }
33
30
  }
34
31
 
35
- // No template gitignore found, create a basic one
36
- const basicGitignore = [
37
- '# Dependencies',
38
- 'node_modules',
39
- '',
40
- '# Logs',
41
- '*.log',
42
- '',
43
- '# Env files',
44
- '.env',
45
- '.env.local'
46
- ].join('\n');
47
-
48
- await writeFile(destPath, basicGitignore, 'utf8');
49
- context.generatedFiles.add(path.relative(context.cwd, destPath));
32
+ return renamedFiles;
50
33
  }
51
34
 
52
35
  /** @type {import('../../internal.d.ts').copyTemplate} */
@@ -63,8 +46,15 @@ async function copyTemplate({ context }) {
63
46
  context.generatedFiles.add(path.relative(context.cwd, destPath));
64
47
  }
65
48
 
66
- // Ensure .gitignore is properly created
67
- await ensureGitignore(context);
49
+ // Process .template files recursively
50
+ const renamedFiles = await processTemplateFiles(context.dest);
51
+
52
+ for (const filePath of renamedFiles) {
53
+ // Remove the old .template entry and add the renamed one
54
+ const templatePath = filePath + TEMPLATE_SUFFIX;
55
+ context.generatedFiles.delete(path.relative(context.cwd, templatePath));
56
+ context.generatedFiles.add(path.relative(context.cwd, filePath));
57
+ }
68
58
  }
69
59
 
70
60
  export default withSpinner('Copy template files', copyTemplate);
@@ -1,15 +1,13 @@
1
1
  import { default as diagnostics } from 'diagnostics';
2
2
  const debug = diagnostics('gasket:cli:generate-files');
3
3
  import fs from 'fs/promises';
4
- import { promisify } from 'util';
5
4
  import Handlebars from 'handlebars';
6
5
  import path from 'path';
7
6
  import mkdirp from 'mkdirp';
8
7
  import chalk from 'chalk';
9
8
  const { dim } = chalk;
10
9
  import { withSpinner } from '../with-spinner.js';
11
- import * as syncGlob from 'glob';
12
- const glob = promisify(syncGlob.default);
10
+ import { glob } from 'glob';
13
11
 
14
12
  const flatten = (acc, values) => (acc || []).concat(values);
15
13
  const reSep = /[/\\]+/;
@@ -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 provide preset and plugins
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 recursively, we need to start it
29
- // with the processPlugins and presets from our initial context
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 – it
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": "7.4.17",
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"
@@ -25,30 +34,29 @@
25
34
  "commander": "^12.1.0",
26
35
  "deepmerge": "^4.3.1",
27
36
  "diagnostics": "^2.0.2",
28
- "glob": "^8.1.0",
37
+ "glob": "^13.0.0",
29
38
  "handlebars": "^4.7.8",
30
39
  "inquirer": "^6.5.2",
31
40
  "json5": "^2.2.3",
32
41
  "mkdirp": "^1.0.4",
33
42
  "ora": "^3.4.0",
34
43
  "semver": "^7.7.1",
35
- "@gasket/core": "^7.7.1",
36
- "@gasket/plugin-command": "^7.6.2",
37
- "@gasket/plugin-docs": "^7.5.2",
38
- "@gasket/plugin-docusaurus": "^7.5.0",
39
- "@gasket/plugin-dynamic-plugins": "^7.5.0",
40
- "@gasket/plugin-git": "^7.4.8",
41
- "@gasket/plugin-logger": "^7.4.0",
42
- "@gasket/plugin-metadata": "^7.5.7",
43
- "@gasket/request": "^7.5.5",
44
- "@gasket/utils": "^7.6.4"
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": "^7.5.5"
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 });