@commercetools-frontend/create-mc-app 22.8.0 → 22.8.2

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.
@@ -6,16 +6,16 @@ import _concatInstanceProperty from '@babel/runtime-corejs3/core-js-stable/insta
6
6
  import semver from 'semver';
7
7
  import _Promise from '@babel/runtime-corejs3/core-js-stable/promise';
8
8
  import _startsWithInstanceProperty from '@babel/runtime-corejs3/core-js-stable/instance/starts-with';
9
- import crypto from 'crypto';
10
- import path from 'path';
11
- import readline from 'readline';
9
+ import crypto from 'node:crypto';
10
+ import path from 'node:path';
11
+ import readline from 'node:readline';
12
12
  import _sliceInstanceProperty from '@babel/runtime-corejs3/core-js-stable/instance/slice';
13
13
  import _mapInstanceProperty from '@babel/runtime-corejs3/core-js-stable/instance/map';
14
14
  import _findInstanceProperty from '@babel/runtime-corejs3/core-js-stable/instance/find';
15
- import fs from 'fs';
15
+ import fs from 'node:fs';
16
16
  import _Object$keys from '@babel/runtime-corejs3/core-js-stable/object/keys';
17
17
  import _Date$now from '@babel/runtime-corejs3/core-js-stable/date/now';
18
- import os from 'os';
18
+ import os from 'node:os';
19
19
  import _Object$getOwnPropertySymbols from '@babel/runtime-corejs3/core-js-stable/object/get-own-property-symbols';
20
20
  import _Object$getOwnPropertyDescriptor from '@babel/runtime-corejs3/core-js-stable/object/get-own-property-descriptor';
21
21
  import _forEachInstanceProperty from '@babel/runtime-corejs3/core-js-stable/instance/for-each';
@@ -33,7 +33,7 @@ import prettier from 'prettier';
33
33
 
34
34
  var pkgJson = {
35
35
  name: "@commercetools-frontend/create-mc-app",
36
- version: "22.8.0",
36
+ version: "22.8.2",
37
37
  description: "Create Merchant Center applications to quickly get up and running",
38
38
  bugs: "https://github.com/commercetools/merchant-center-application-kit/issues",
39
39
  repository: {
@@ -75,6 +75,15 @@ var pkgJson = {
75
75
  }
76
76
  };
77
77
 
78
+ const applicationTypes = {
79
+ 'custom-application': 'custom-application',
80
+ 'custom-view': 'custom-view'
81
+ };
82
+ const availableTemplates = {
83
+ starter: 'starter',
84
+ 'starter-typescript': 'starter-typescript'
85
+ };
86
+
78
87
  async function getLatestReleaseVersion() {
79
88
  const commandResult = await execa.command('npm view @commercetools-frontend/create-mc-app --json', {
80
89
  encoding: 'utf-8'
@@ -142,31 +151,48 @@ const resolveFilePathByExtension = requestedModule => {
142
151
  return _concatInstanceProperty(_context4 = "".concat(requestedModule)).call(_context4, fileExtension);
143
152
  };
144
153
 
145
- const availableTemplates = {
146
- starter: 'starter',
147
- 'starter-typescript': 'starter-typescript'
154
+ const throwIfApplicationTypeIsNotSupported = applicationType => {
155
+ switch (applicationType) {
156
+ case applicationTypes['custom-view']:
157
+ {
158
+ if (process.env.ENABLE_EXPERIMENTAL_CUSTOM_VIEWS !== 'true') {
159
+ throw new Error("Custom Views generation is not yet supported.");
160
+ }
161
+ break;
162
+ }
163
+ case applicationTypes['custom-application']:
164
+ break;
165
+ default:
166
+ {
167
+ var _context;
168
+ const applicationTypesList = _Object$keys(applicationTypes).toString();
169
+ throw new Error(_concatInstanceProperty(_context = "The provided application type \"".concat(applicationType, "\" does not exist. Available types are \"")).call(_context, applicationTypesList, "\". Make sure you are also using the latest version of \"@commercetools-frontend/create-mc-app\"."));
170
+ }
171
+ }
148
172
  };
149
173
  const throwIfTemplateIsNotSupported = templateName => {
150
- var _context;
151
174
  switch (templateName) {
152
175
  case availableTemplates.starter:
153
176
  case availableTemplates['starter-typescript']:
154
177
  break;
155
178
  default:
156
- const templateNamesList = _Object$keys(availableTemplates).toString();
157
- throw new Error(_concatInstanceProperty(_context = "The provided template name \"".concat(templateName, "\" does not exist. Available templates are \"")).call(_context, templateNamesList, "\". Make sure you are also using the latest version of \"@commercetools-frontend/create-mc-app\"."));
179
+ {
180
+ var _context2;
181
+ const templateNamesList = _Object$keys(availableTemplates).toString();
182
+ throw new Error(_concatInstanceProperty(_context2 = "The provided template name \"".concat(templateName, "\" does not exist. Available templates are \"")).call(_context2, templateNamesList, "\". Make sure you are also using the latest version of \"@commercetools-frontend/create-mc-app\"."));
183
+ }
158
184
  }
159
185
  };
160
186
  const throwIfProjectDirectoryExists = (dirName, dirPath) => {
161
187
  if (fs.existsSync(dirPath)) {
162
- var _context2;
163
- throw new Error(_concatInstanceProperty(_context2 = "A directory named \"".concat(dirName, "\" already exists at this location \"")).call(_context2, dirPath, "\". Please choose a different project name or remove the directory, then try running the command again."));
188
+ var _context3;
189
+ throw new Error(_concatInstanceProperty(_context3 = "A directory named \"".concat(dirName, "\" already exists at this location \"")).call(_context3, dirPath, "\". Please choose a different project name or remove the directory, then try running the command again."));
164
190
  }
165
191
  };
166
192
  const throwIfTemplateVersionDoesNotExist = (templateName, templateFolderPath, versionToCheck) => {
167
193
  if (!fs.existsSync(templateFolderPath)) {
168
- var _context3;
169
- throw new Error(_concatInstanceProperty(_context3 = "The downloaded template \"".concat(templateName, "\" does not exist for the given version \"")).call(_context3, versionToCheck, "\". Check the releases page if you are looking for a specific version: https://github.com/commercetools/merchant-center-application-kit/releases"));
194
+ var _context4;
195
+ throw new Error(_concatInstanceProperty(_context4 = "The downloaded template \"".concat(templateName, "\" does not exist for the given version \"")).call(_context4, versionToCheck, "\". Check the releases page if you are looking for a specific version: https://github.com/commercetools/merchant-center-application-kit/releases"));
170
196
  }
171
197
  // In case the version is semver (usually release tags) we check that
172
198
  // the cloned repository contains the template matching the given version
@@ -176,8 +202,8 @@ const throwIfTemplateVersionDoesNotExist = (templateName, templateFolderPath, ve
176
202
  }));
177
203
  const versionAsNumber = versionToCheck.replace('v', '');
178
204
  if (templatePackageJson.version !== versionAsNumber) {
179
- var _context4, _context5;
180
- throw new Error(_concatInstanceProperty(_context4 = _concatInstanceProperty(_context5 = "The downloaded template \"".concat(templateName, "\" does not match the version \"")).call(_context5, versionAsNumber, "\", instead got \"")).call(_context4, templatePackageJson.version, "\". Check the releases page if you want to provide a specific version: https://github.com/commercetools/merchant-center-application-kit/releases"));
205
+ var _context5, _context6;
206
+ throw new Error(_concatInstanceProperty(_context5 = _concatInstanceProperty(_context6 = "The downloaded template \"".concat(templateName, "\" does not match the version \"")).call(_context6, versionAsNumber, "\", instead got \"")).call(_context5, templatePackageJson.version, "\". Check the releases page if you want to provide a specific version: https://github.com/commercetools/merchant-center-application-kit/releases"));
181
207
  }
182
208
  }
183
209
  };
@@ -189,14 +215,17 @@ const throwIfInitialProjectKeyIsMissing = initialProjectKey => {
189
215
  const throwIfNodeVersionIsNotSupported = (currentNodeVersion, expectedVersionRange) => {
190
216
  const hasValidNodeVersion = semver.satisfies(currentNodeVersion, expectedVersionRange);
191
217
  if (!hasValidNodeVersion) {
192
- var _context6;
193
- throw new Error(_concatInstanceProperty(_context6 = "You are running Node ".concat(currentNodeVersion, " but create-mc-app requires Node ")).call(_context6, expectedVersionRange, ". Please update your version of Node."));
218
+ var _context7;
219
+ throw new Error(_concatInstanceProperty(_context7 = "You are running Node ".concat(currentNodeVersion, " but create-mc-app requires Node ")).call(_context7, expectedVersionRange, ". Please update your version of Node."));
194
220
  }
195
221
  };
196
222
 
197
223
  const question = (rl, value) => new _Promise(resolve => rl.question(value, resolve));
198
224
  const getEntryPointUriPath = async (rl, options) => {
199
225
  var _context;
226
+ if (options.applicationType === applicationTypes['custom-view']) {
227
+ return;
228
+ }
200
229
  if (options.entryPointUriPath) {
201
230
  return options.entryPointUriPath;
202
231
  }
@@ -227,6 +256,7 @@ async function processOptions(projectDirectoryName, options) {
227
256
  const templateName = options.template;
228
257
 
229
258
  // Validate options
259
+ throwIfApplicationTypeIsNotSupported(options.applicationType);
230
260
  throwIfProjectDirectoryExists(projectDirectoryName, projectDirectoryPath);
231
261
  throwIfTemplateIsNotSupported(templateName);
232
262
 
@@ -239,6 +269,7 @@ async function processOptions(projectDirectoryName, options) {
239
269
  const initialProjectKey = await getInitialProjectKey(rl, options);
240
270
  rl.close();
241
271
  return {
272
+ applicationType: options.applicationType,
242
273
  projectDirectoryName,
243
274
  projectDirectoryPath,
244
275
  templateName,
@@ -258,7 +289,7 @@ function downloadTemplate(options) {
258
289
  const tmpDir = os.tmpdir();
259
290
  const tmpFolderNameForClonedRepository = ['merchant-center-application-kit', '--', options.tagOrBranchVersion, '--', _Date$now().toString()].join('');
260
291
  const clonedRepositoryPath = path.join(tmpDir, tmpFolderNameForClonedRepository);
261
- const templateFolderPath = path.join(clonedRepositoryPath, 'application-templates', options.templateName);
292
+ const templateFolderPath = path.join(clonedRepositoryPath, options.applicationType === applicationTypes['custom-view'] ? 'custom-views-templates' : 'application-templates', options.templateName);
262
293
  return new Listr([{
263
294
  title: "Cloning repository using branch ".concat(options.tagOrBranchVersion),
264
295
  task: async () => {
@@ -370,10 +401,11 @@ function updatePackageJson(options, releaseVersion) {
370
401
  };
371
402
  }
372
403
 
373
- function replaceApplicationInfoInCustomApplicationConfig(filePath, options) {
374
- const appName = wordify(options.entryPointUriPath);
404
+ function replaceApplicationInfoInApplicationConfig(filePath, options) {
375
405
  const result = transformFileSync(filePath, {
376
- plugins: [function replaceCustomApplicationConfig() {
406
+ plugins: [function replaceConfig() {
407
+ var _options$entryPointUr;
408
+ const appName = wordify((_options$entryPointUr = options.entryPointUriPath) !== null && _options$entryPointUr !== void 0 ? _options$entryPointUr : options.projectDirectoryName);
377
409
  return {
378
410
  visitor: {
379
411
  Identifier(nodePath) {
@@ -387,7 +419,7 @@ function replaceApplicationInfoInCustomApplicationConfig(filePath, options) {
387
419
  }) && nodePath.parent.type === 'ObjectProperty') {
388
420
  nodePath.parent.value = types.stringLiteral(options.initialProjectKey);
389
421
  }
390
- if (nodePath.isIdentifier({
422
+ if (options.applicationType === applicationTypes['custom-application'] && nodePath.isIdentifier({
391
423
  name: 'defaultLabel'
392
424
  })) {
393
425
  const isMainMenuLinkParent = nodePath.findParent(parentPath => parentPath.isIdentifier({
@@ -411,12 +443,22 @@ function replaceApplicationInfoInCustomApplicationConfig(filePath, options) {
411
443
  });
412
444
  }
413
445
  }
414
- function updateCustomApplicationConfig(options) {
446
+ function getApplicationConfigName(options) {
447
+ switch (options.applicationType) {
448
+ case applicationTypes['custom-application']:
449
+ return 'custom-application-config';
450
+ case applicationTypes['custom-view']:
451
+ return 'custom-view-config';
452
+ default:
453
+ throw new Error("Unknown application type ".concat(options.applicationType));
454
+ }
455
+ }
456
+ function updateApplicationConfig(options) {
415
457
  return {
416
- title: 'Updating Custom Applications config',
458
+ title: 'Updating application config file',
417
459
  task: () => {
418
- const customApplicationConfigPath = resolveFilePathByExtension(path.join(options.projectDirectoryPath, 'custom-application-config'));
419
- replaceApplicationInfoInCustomApplicationConfig(customApplicationConfigPath, options);
460
+ const configPath = resolveFilePathByExtension(path.join(options.projectDirectoryPath, getApplicationConfigName(options)));
461
+ replaceApplicationInfoInApplicationConfig(configPath, options);
420
462
  }
421
463
  };
422
464
  }
@@ -447,6 +489,7 @@ function replaceEntryPointUriPathInConstants(filePath, options) {
447
489
  function updateApplicationConstants(options) {
448
490
  return {
449
491
  title: 'Updating application constants',
492
+ enabled: options.applicationType === applicationTypes['custom-application'],
450
493
  task: () => {
451
494
  const applicationConstantsPath = resolveFilePathByExtension(path.join(options.projectDirectoryPath, 'src/constants'));
452
495
  replaceEntryPointUriPathInConstants(applicationConstantsPath, options);
@@ -465,8 +508,10 @@ process.on('unhandledRejection', err => {
465
508
  });
466
509
  const run = () => {
467
510
  // Default command
468
- cli.command('[project-directory]').usage('[project-directory]\n\n Bootstraps a new Custom Application project using one of the predefined templates.').option('--template <name>', '(optional) The name of the template to install.', {
469
- default: 'starter'
511
+ cli.command('[project-directory]').usage('[project-directory]\n\n Bootstraps a new Custom Application project using one of the predefined templates.').option('--application-type <type>', '(optional) The type of the application to create: custom-application (default) or custom-view.', {
512
+ default: applicationTypes['custom-application']
513
+ }).option('--template <name>', '(optional) The name of the template to install.', {
514
+ default: availableTemplates.starter
470
515
  }).option('--template-version <version>', '(optional) The version of the template to install (either a git tag or a git branch of the "commercetools/merchant-center-application-kit" repository).', {
471
516
  default: 'main'
472
517
  }).option('--skip-install', '(optional) Skip installing the dependencies after cloning the template.', {
@@ -482,17 +527,18 @@ const run = () => {
482
527
  const releaseVersion = await getLatestReleaseVersion();
483
528
  hintOutdatedVersion(pkgJson.version, releaseVersion);
484
529
  console.log('');
485
- console.log("Documentation available at https://docs.commercetools.com/custom-applications");
530
+ console.log( // TODO: Use link based on the application type
531
+ "Documentation available at https://docs.commercetools.com/custom-applications");
486
532
  console.log('');
487
533
  const taskOptions = await processOptions(projectDirectory, options);
488
534
  const shouldInstallDependencies = !options.skipInstall ||
489
535
  // TODO: remove once we manage to ensure the package manager is installed, for example via Corepack.
490
536
  options.packageManager === 'pnpm';
491
- const taskList = new Listr(_filterInstanceProperty(_context = [downloadTemplate(taskOptions), updatePackageJson(taskOptions, releaseVersion), updateCustomApplicationConfig(taskOptions), updateApplicationConstants(taskOptions), shouldInstallDependencies && installDependencies(taskOptions)]).call(_context, Boolean));
537
+ const taskList = new Listr(_filterInstanceProperty(_context = [downloadTemplate(taskOptions), updatePackageJson(taskOptions, releaseVersion), updateApplicationConfig(taskOptions), updateApplicationConstants(taskOptions), shouldInstallDependencies && installDependencies(taskOptions)]).call(_context, Boolean));
492
538
  await taskList.run();
493
539
  const packageManager = getPreferredPackageManager(taskOptions);
494
540
  console.log('');
495
- console.log("\uD83C\uDF89 \uD83C\uDF89 \uD83C\uDF89 The Custom Application has been created in the \"".concat(taskOptions.projectDirectoryName, "\" folder."));
541
+ console.log("\uD83C\uDF89 \uD83C\uDF89 \uD83C\uDF89 The application has been created in the \"".concat(taskOptions.projectDirectoryName, "\" folder."));
496
542
  console.log('');
497
543
  console.log("To get started:");
498
544
  console.log("$ cd ".concat(taskOptions.projectDirectoryName));
@@ -501,7 +547,8 @@ const run = () => {
501
547
  }
502
548
  console.log("$ ".concat(packageManager, " start"));
503
549
  console.log('');
504
- console.log("Visit https://docs.commercetools.com/custom-applications for more info about developing Custom Applications. Enjoy \uD83D\uDE80");
550
+ console.log( // TODO: Use link based on the application type
551
+ "Visit https://docs.commercetools.com/custom-applications for more info about developing Custom Applications. Enjoy \uD83D\uDE80");
505
552
  });
506
553
  cli.help();
507
554
  cli.version(pkgJson.version);
@@ -0,0 +1,9 @@
1
+ declare const applicationTypes: {
2
+ readonly 'custom-application': "custom-application";
3
+ readonly 'custom-view': "custom-view";
4
+ };
5
+ declare const availableTemplates: {
6
+ readonly starter: "starter";
7
+ readonly 'starter-typescript': "starter-typescript";
8
+ };
9
+ export { applicationTypes, availableTemplates };
@@ -1,5 +1,5 @@
1
1
  export { default as downloadTemplate } from './download-template';
2
2
  export { default as installDependencies } from './install-dependencies';
3
3
  export { default as updatePackageJson } from './update-package-json';
4
- export { default as updateCustomApplicationConfig } from './update-custom-application-config';
4
+ export { default as updateApplicationConfig } from './update-application-config';
5
5
  export { default as updateApplicationConstants } from './update-application-constants';
@@ -0,0 +1,4 @@
1
+ import type { ListrTask } from 'listr2';
2
+ import type { TCliTaskOptions } from '../types';
3
+ declare function updateApplicationConfig(options: TCliTaskOptions): ListrTask;
4
+ export default updateApplicationConfig;
@@ -1,9 +1,12 @@
1
+ import { applicationTypes, availableTemplates } from './constants';
1
2
  export type TCliGlobalOptions = {
2
3
  '--'?: string[];
3
4
  };
4
- export type TTemplate = 'starter' | 'starter-typescript';
5
+ export type TApplicationType = keyof typeof applicationTypes;
6
+ export type TTemplate = keyof typeof availableTemplates;
5
7
  export type TPackageManager = 'npm' | 'yarn' | 'pnpm';
6
8
  export type TCliCommandOptions = {
9
+ applicationType: TApplicationType;
7
10
  template: TTemplate;
8
11
  templateVersion: string;
9
12
  skipInstall: boolean;
@@ -13,11 +16,12 @@ export type TCliCommandOptions = {
13
16
  packageManager?: TPackageManager;
14
17
  };
15
18
  export type TCliTaskOptions = {
19
+ applicationType: TApplicationType;
16
20
  projectDirectoryName: string;
17
21
  projectDirectoryPath: string;
18
22
  templateName: TCliCommandOptions['template'];
19
23
  tagOrBranchVersion: string;
20
- entryPointUriPath: string;
24
+ entryPointUriPath?: string;
21
25
  initialProjectKey: string;
22
26
  packageManager: TCliCommandOptions['packageManager'];
23
27
  };
@@ -1,4 +1,4 @@
1
- import type { TCliTaskOptions, TPackageManager } from './types';
1
+ import type { TApplicationType, TCliTaskOptions, TPackageManager } from './types';
2
2
  declare const isSemVer: (version: string) => boolean;
3
3
  declare const shouldUseYarn: () => boolean;
4
4
  declare const getPreferredPackageManager: (options: TCliTaskOptions) => TPackageManager;
@@ -7,4 +7,5 @@ declare const slugify: (name: string) => string;
7
7
  declare const upperFirst: (value: string) => string;
8
8
  declare const wordify: (slug: string) => string;
9
9
  declare const resolveFilePathByExtension: (requestedModule: string) => string;
10
- export { isSemVer, shouldUseYarn, slugify, wordify, upperFirst, resolveFilePathByExtension, getPreferredPackageManager, getInstallCommand, };
10
+ declare const isCustomView: (applicationType: TApplicationType) => boolean;
11
+ export { isSemVer, shouldUseYarn, slugify, wordify, upperFirst, resolveFilePathByExtension, getPreferredPackageManager, getInstallCommand, isCustomView, };
@@ -1,7 +1,8 @@
1
- import type { TTemplate } from './types';
1
+ import type { TApplicationType, TTemplate } from './types';
2
+ declare const throwIfApplicationTypeIsNotSupported: (applicationType: TApplicationType) => void;
2
3
  declare const throwIfTemplateIsNotSupported: (templateName: TTemplate) => void;
3
4
  declare const throwIfProjectDirectoryExists: (dirName: string, dirPath: string) => void;
4
5
  declare const throwIfTemplateVersionDoesNotExist: (templateName: string, templateFolderPath: string, versionToCheck: string) => void;
5
6
  declare const throwIfInitialProjectKeyIsMissing: (initialProjectKey?: string) => void;
6
7
  declare const throwIfNodeVersionIsNotSupported: (currentNodeVersion: string, expectedVersionRange: string) => void;
7
- export { throwIfTemplateIsNotSupported, throwIfProjectDirectoryExists, throwIfTemplateVersionDoesNotExist, throwIfInitialProjectKeyIsMissing, throwIfNodeVersionIsNotSupported, };
8
+ export { throwIfApplicationTypeIsNotSupported, throwIfTemplateIsNotSupported, throwIfProjectDirectoryExists, throwIfTemplateVersionDoesNotExist, throwIfInitialProjectKeyIsMissing, throwIfNodeVersionIsNotSupported, };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@commercetools-frontend/create-mc-app",
3
- "version": "22.8.0",
3
+ "version": "22.8.2",
4
4
  "description": "Create Merchant Center applications to quickly get up and running",
5
5
  "bugs": "https://github.com/commercetools/merchant-center-application-kit/issues",
6
6
  "repository": {
package/src/cli.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import { cac } from 'cac';
2
2
  import { Listr, type ListrTask } from 'listr2';
3
3
  import pkgJson from '../package.json';
4
+ import { applicationTypes, availableTemplates } from './constants';
4
5
  import getLatestReleaseVersion from './get-latest-release-version';
5
6
  import hintOutdatedVersion from './hint-outdated-version';
6
7
  import processOptions from './process-options';
@@ -27,10 +28,15 @@ const run = () => {
27
28
  .usage(
28
29
  '[project-directory]\n\n Bootstraps a new Custom Application project using one of the predefined templates.'
29
30
  )
31
+ .option(
32
+ '--application-type <type>',
33
+ '(optional) The type of the application to create: custom-application (default) or custom-view.',
34
+ { default: applicationTypes['custom-application'] }
35
+ )
30
36
  .option(
31
37
  '--template <name>',
32
38
  '(optional) The name of the template to install.',
33
- { default: 'starter' }
39
+ { default: availableTemplates.starter }
34
40
  )
35
41
  .option(
36
42
  '--template-version <version>',
@@ -71,6 +77,7 @@ const run = () => {
71
77
 
72
78
  console.log('');
73
79
  console.log(
80
+ // TODO: Use link based on the application type
74
81
  `Documentation available at https://docs.commercetools.com/custom-applications`
75
82
  );
76
83
  console.log('');
@@ -86,7 +93,7 @@ const run = () => {
86
93
  [
87
94
  tasks.downloadTemplate(taskOptions),
88
95
  tasks.updatePackageJson(taskOptions, releaseVersion),
89
- tasks.updateCustomApplicationConfig(taskOptions),
96
+ tasks.updateApplicationConfig(taskOptions),
90
97
  tasks.updateApplicationConstants(taskOptions),
91
98
  shouldInstallDependencies && tasks.installDependencies(taskOptions),
92
99
  ].filter(Boolean) as ListrTask[]
@@ -97,7 +104,7 @@ const run = () => {
97
104
 
98
105
  console.log('');
99
106
  console.log(
100
- `🎉 🎉 🎉 The Custom Application has been created in the "${taskOptions.projectDirectoryName}" folder.`
107
+ `🎉 🎉 🎉 The application has been created in the "${taskOptions.projectDirectoryName}" folder.`
101
108
  );
102
109
  console.log('');
103
110
  console.log(`To get started:`);
@@ -108,6 +115,7 @@ const run = () => {
108
115
  console.log(`$ ${packageManager} start`);
109
116
  console.log('');
110
117
  console.log(
118
+ // TODO: Use link based on the application type
111
119
  `Visit https://docs.commercetools.com/custom-applications for more info about developing Custom Applications. Enjoy 🚀`
112
120
  );
113
121
  });
@@ -0,0 +1,11 @@
1
+ const applicationTypes = {
2
+ 'custom-application': 'custom-application',
3
+ 'custom-view': 'custom-view',
4
+ } as const;
5
+
6
+ const availableTemplates = {
7
+ starter: 'starter',
8
+ 'starter-typescript': 'starter-typescript',
9
+ } as const;
10
+
11
+ export { applicationTypes, availableTemplates };
@@ -1,12 +1,14 @@
1
- import crypto from 'crypto';
2
- import path from 'path';
3
- import readline, { type Interface } from 'readline';
1
+ import crypto from 'node:crypto';
2
+ import path from 'node:path';
3
+ import readline, { type Interface } from 'node:readline';
4
+ import { applicationTypes } from './constants';
4
5
  import type { TCliCommandOptions, TCliTaskOptions } from './types';
5
6
  import { isSemVer } from './utils';
6
7
  import {
7
8
  throwIfTemplateIsNotSupported,
8
9
  throwIfProjectDirectoryExists,
9
10
  throwIfInitialProjectKeyIsMissing,
11
+ throwIfApplicationTypeIsNotSupported,
10
12
  } from './validations';
11
13
 
12
14
  const question = (rl: Interface, value: string) =>
@@ -16,6 +18,10 @@ const getEntryPointUriPath = async (
16
18
  rl: Interface,
17
19
  options: TCliCommandOptions
18
20
  ) => {
21
+ if (options.applicationType === applicationTypes['custom-view']) {
22
+ return;
23
+ }
24
+
19
25
  if (options.entryPointUriPath) {
20
26
  return options.entryPointUriPath;
21
27
  }
@@ -72,6 +78,7 @@ async function processOptions(
72
78
  const templateName = options.template;
73
79
 
74
80
  // Validate options
81
+ throwIfApplicationTypeIsNotSupported(options.applicationType);
75
82
  throwIfProjectDirectoryExists(projectDirectoryName, projectDirectoryPath);
76
83
  throwIfTemplateIsNotSupported(templateName);
77
84
 
@@ -85,6 +92,7 @@ async function processOptions(
85
92
  rl.close();
86
93
 
87
94
  return {
95
+ applicationType: options.applicationType,
88
96
  projectDirectoryName,
89
97
  projectDirectoryPath,
90
98
  templateName,
@@ -1,8 +1,9 @@
1
- import fs from 'fs';
2
- import os from 'os';
3
- import path from 'path';
1
+ import fs from 'node:fs';
2
+ import os from 'node:os';
3
+ import path from 'node:path';
4
4
  import execa from 'execa';
5
5
  import { Listr, type ListrTask } from 'listr2';
6
+ import { applicationTypes } from '../constants';
6
7
  import type { TCliTaskOptions } from '../types';
7
8
  import { throwIfTemplateVersionDoesNotExist } from '../validations';
8
9
 
@@ -26,7 +27,9 @@ function downloadTemplate(options: TCliTaskOptions): ListrTask {
26
27
  );
27
28
  const templateFolderPath = path.join(
28
29
  clonedRepositoryPath,
29
- 'application-templates',
30
+ options.applicationType === applicationTypes['custom-view']
31
+ ? 'custom-views-templates'
32
+ : 'application-templates',
30
33
  options.templateName
31
34
  );
32
35
  return new Listr([
@@ -1,5 +1,5 @@
1
1
  export { default as downloadTemplate } from './download-template';
2
2
  export { default as installDependencies } from './install-dependencies';
3
3
  export { default as updatePackageJson } from './update-package-json';
4
- export { default as updateCustomApplicationConfig } from './update-custom-application-config';
4
+ export { default as updateApplicationConfig } from './update-application-config';
5
5
  export { default as updateApplicationConstants } from './update-application-constants';
@@ -1,21 +1,23 @@
1
- import fs from 'fs';
2
- import os from 'os';
3
- import path from 'path';
1
+ import fs from 'node:fs';
2
+ import os from 'node:os';
3
+ import path from 'node:path';
4
4
  import { transformFileSync, types, type PluginItem } from '@babel/core';
5
5
  import type { ListrTask } from 'listr2';
6
6
  import prettier from 'prettier';
7
+ import { applicationTypes } from '../constants';
7
8
  import type { TCliTaskOptions } from '../types';
8
9
  import { wordify, resolveFilePathByExtension } from '../utils';
9
10
 
10
- function replaceApplicationInfoInCustomApplicationConfig(
11
+ function replaceApplicationInfoInApplicationConfig(
11
12
  filePath: string,
12
13
  options: TCliTaskOptions
13
14
  ) {
14
- const appName = wordify(options.entryPointUriPath);
15
-
16
15
  const result = transformFileSync(filePath, {
17
16
  plugins: [
18
- function replaceCustomApplicationConfig(): PluginItem {
17
+ function replaceConfig(): PluginItem {
18
+ const appName = wordify(
19
+ options.entryPointUriPath ?? options.projectDirectoryName
20
+ );
19
21
  return {
20
22
  visitor: {
21
23
  Identifier(nodePath) {
@@ -33,7 +35,11 @@ function replaceApplicationInfoInCustomApplicationConfig(
33
35
  options.initialProjectKey
34
36
  );
35
37
  }
36
- if (nodePath.isIdentifier({ name: 'defaultLabel' })) {
38
+ if (
39
+ options.applicationType ===
40
+ applicationTypes['custom-application'] &&
41
+ nodePath.isIdentifier({ name: 'defaultLabel' })
42
+ ) {
37
43
  const isMainMenuLinkParent = nodePath.findParent((parentPath) =>
38
44
  parentPath.isIdentifier({
39
45
  name: 'mainMenuLink',
@@ -68,19 +74,30 @@ function replaceApplicationInfoInCustomApplicationConfig(
68
74
  }
69
75
  }
70
76
 
71
- function updateCustomApplicationConfig(options: TCliTaskOptions): ListrTask {
77
+ function getApplicationConfigName(options: TCliTaskOptions) {
78
+ switch (options.applicationType) {
79
+ case applicationTypes['custom-application']:
80
+ return 'custom-application-config';
81
+ case applicationTypes['custom-view']:
82
+ return 'custom-view-config';
83
+ default:
84
+ throw new Error(`Unknown application type ${options.applicationType}`);
85
+ }
86
+ }
87
+
88
+ function updateApplicationConfig(options: TCliTaskOptions): ListrTask {
72
89
  return {
73
- title: 'Updating Custom Applications config',
90
+ title: 'Updating application config file',
74
91
  task: () => {
75
- const customApplicationConfigPath = resolveFilePathByExtension(
76
- path.join(options.projectDirectoryPath, 'custom-application-config')
77
- );
78
- replaceApplicationInfoInCustomApplicationConfig(
79
- customApplicationConfigPath,
80
- options
92
+ const configPath = resolveFilePathByExtension(
93
+ path.join(
94
+ options.projectDirectoryPath,
95
+ getApplicationConfigName(options)
96
+ )
81
97
  );
98
+ replaceApplicationInfoInApplicationConfig(configPath, options);
82
99
  },
83
100
  };
84
101
  }
85
102
 
86
- export default updateCustomApplicationConfig;
103
+ export default updateApplicationConfig;
@@ -1,9 +1,10 @@
1
- import fs from 'fs';
2
- import os from 'os';
3
- import path from 'path';
1
+ import fs from 'node:fs';
2
+ import os from 'node:os';
3
+ import path from 'node:path';
4
4
  import { type PluginItem, transformFileSync, types } from '@babel/core';
5
5
  import type { ListrTask } from 'listr2';
6
6
  import prettier from 'prettier';
7
+ import { applicationTypes } from '../constants';
7
8
  import type { TCliTaskOptions } from '../types';
8
9
  import { resolveFilePathByExtension } from '../utils';
9
10
 
@@ -22,7 +23,7 @@ function replaceEntryPointUriPathInConstants(
22
23
  nodePath.node.id.name === 'entryPointUriPath'
23
24
  ) {
24
25
  nodePath.node.init = types.stringLiteral(
25
- options.entryPointUriPath
26
+ options.entryPointUriPath!
26
27
  );
27
28
  }
28
29
  },
@@ -50,6 +51,7 @@ function replaceEntryPointUriPathInConstants(
50
51
  function updateApplicationConstants(options: TCliTaskOptions): ListrTask {
51
52
  return {
52
53
  title: 'Updating application constants',
54
+ enabled: options.applicationType === applicationTypes['custom-application'],
53
55
  task: () => {
54
56
  const applicationConstantsPath = resolveFilePathByExtension(
55
57
  path.join(options.projectDirectoryPath, 'src/constants')
@@ -1,6 +1,6 @@
1
- import fs from 'fs';
2
- import os from 'os';
3
- import path from 'path';
1
+ import fs from 'node:fs';
2
+ import os from 'node:os';
3
+ import path from 'node:path';
4
4
  import type { ListrTask } from 'listr2';
5
5
  import type { TCliTaskOptions } from '../types';
6
6
  import { getPreferredPackageManager, slugify } from '../utils';