@commercetools-frontend/create-mc-app 21.9.0 → 21.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -0
- package/README.md +1 -12
- package/bin/cli.js +1 -90
- package/dist/commercetools-frontend-create-mc-app.cjs.d.ts +1 -0
- package/dist/commercetools-frontend-create-mc-app.cjs.dev.js +792 -0
- package/dist/commercetools-frontend-create-mc-app.cjs.js +7 -0
- package/dist/commercetools-frontend-create-mc-app.cjs.prod.js +787 -0
- package/dist/commercetools-frontend-create-mc-app.esm.js +764 -0
- package/dist/declarations/src/cli.d.ts +2 -0
- package/dist/declarations/src/hint-outdated-version.d.ts +2 -0
- package/dist/declarations/src/index.d.ts +2 -0
- package/dist/declarations/src/process-options.d.ts +3 -0
- package/dist/declarations/src/tasks/download-template.d.ts +4 -0
- package/dist/declarations/src/tasks/index.d.ts +5 -0
- package/dist/declarations/src/tasks/install-dependencies.d.ts +4 -0
- package/dist/declarations/src/tasks/update-application-constants.d.ts +4 -0
- package/dist/declarations/src/tasks/update-custom-application-config.d.ts +4 -0
- package/dist/declarations/src/tasks/update-package-json.d.ts +4 -0
- package/dist/declarations/src/types.d.ts +19 -0
- package/dist/declarations/src/utils.d.ts +7 -0
- package/dist/declarations/src/validations.d.ts +7 -0
- package/package.json +7 -3
- package/src/cli.ts +109 -0
- package/src/hint-outdated-version.ts +39 -0
- package/src/index.ts +3 -0
- package/src/process-options.ts +97 -0
- package/src/tasks/{download-template.js → download-template.ts} +11 -8
- package/src/tasks/index.ts +5 -0
- package/src/tasks/{install-dependencies.js → install-dependencies.ts} +8 -4
- package/src/tasks/update-application-constants.ts +61 -0
- package/src/tasks/update-custom-application-config.ts +85 -0
- package/src/tasks/{update-package-json.js → update-package-json.ts} +10 -6
- package/src/types.ts +21 -0
- package/src/utils.ts +41 -0
- package/src/{validations.js → validations.ts} +44 -15
- package/tsconfig.json +6 -0
- package/src/hint-outdated-version.js +0 -34
- package/src/index.js +0 -12
- package/src/parse-arguments.js +0 -87
- package/src/tasks/index.js +0 -13
- package/src/tasks/update-application-constants.js +0 -48
- package/src/tasks/update-custom-application-config.js +0 -64
- package/src/utils.js +0 -56
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { default as downloadTemplate } from './download-template';
|
|
2
|
+
export { default as installDependencies } from './install-dependencies';
|
|
3
|
+
export { default as updatePackageJson } from './update-package-json';
|
|
4
|
+
export { default as updateCustomApplicationConfig } from './update-custom-application-config';
|
|
5
|
+
export { default as updateApplicationConstants } from './update-application-constants';
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export declare type TCliGlobalOptions = {
|
|
2
|
+
'--'?: string[];
|
|
3
|
+
};
|
|
4
|
+
export declare type TCliCommandOptions = {
|
|
5
|
+
template: 'starter' | 'starter-typescript';
|
|
6
|
+
templateVersion: string;
|
|
7
|
+
skipInstall: boolean;
|
|
8
|
+
yes: boolean;
|
|
9
|
+
entryPointUriPath?: string;
|
|
10
|
+
initialProjectKey?: string;
|
|
11
|
+
};
|
|
12
|
+
export declare type TCliTaskOptions = {
|
|
13
|
+
projectDirectoryName: string;
|
|
14
|
+
projectDirectoryPath: string;
|
|
15
|
+
templateName: TCliCommandOptions['template'];
|
|
16
|
+
tagOrBranchVersion: string;
|
|
17
|
+
entryPointUriPath: string;
|
|
18
|
+
initialProjectKey: string;
|
|
19
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
declare const isSemVer: (version: string) => boolean;
|
|
2
|
+
declare const shouldUseYarn: () => boolean;
|
|
3
|
+
declare const slugify: (name: string) => string;
|
|
4
|
+
declare const upperFirst: (value: string) => string;
|
|
5
|
+
declare const wordify: (slug: string) => string;
|
|
6
|
+
declare const resolveFilePathByExtension: (requestedModule: string) => string;
|
|
7
|
+
export { isSemVer, shouldUseYarn, slugify, wordify, upperFirst, resolveFilePathByExtension, };
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { TCliCommandOptions } from './types';
|
|
2
|
+
declare const throwIfTemplateIsNotSupported: (templateName: TCliCommandOptions['template']) => void;
|
|
3
|
+
declare const throwIfProjectDirectoryExists: (dirName: string, dirPath: string) => void;
|
|
4
|
+
declare const throwIfTemplateVersionDoesNotExist: (templateName: string, templateFolderPath: string, versionToCheck: string) => void;
|
|
5
|
+
declare const throwIfInitialProjectKeyIsMissing: (initialProjectKey?: string) => void;
|
|
6
|
+
declare const throwIfNodeVersionIsNotSupported: (currentNodeVersion: string, expectedVersionRange: string) => void;
|
|
7
|
+
export { 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": "21.
|
|
3
|
+
"version": "21.10.0",
|
|
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": {
|
|
@@ -14,12 +14,16 @@
|
|
|
14
14
|
"publishConfig": {
|
|
15
15
|
"access": "public"
|
|
16
16
|
},
|
|
17
|
+
"main": "dist/commercetools-frontend-create-mc-app.cjs.js",
|
|
18
|
+
"module": "dist/commercetools-frontend-create-mc-app.esm.js",
|
|
17
19
|
"bin": "./bin/cli.js",
|
|
18
20
|
"dependencies": {
|
|
19
21
|
"@babel/core": "^7.18.6",
|
|
22
|
+
"@babel/runtime": "^7.18.6",
|
|
23
|
+
"@babel/runtime-corejs3": "^7.18.6",
|
|
24
|
+
"cac": "6.7.12",
|
|
20
25
|
"execa": "5.1.1",
|
|
21
|
-
"
|
|
22
|
-
"mri": "1.2.0",
|
|
26
|
+
"listr2": "4.0.5",
|
|
23
27
|
"prettier": "2.6.2",
|
|
24
28
|
"rcfile": "1.0.3",
|
|
25
29
|
"semver": "7.3.7"
|
package/src/cli.ts
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { cac } from 'cac';
|
|
2
|
+
import { Listr, type ListrTask } from 'listr2';
|
|
3
|
+
import * as tasks from './tasks';
|
|
4
|
+
import { throwIfNodeVersionIsNotSupported } from './validations';
|
|
5
|
+
import { shouldUseYarn } from './utils';
|
|
6
|
+
import hintOutdatedVersion from './hint-outdated-version';
|
|
7
|
+
import processOptions from './process-options';
|
|
8
|
+
import type { TCliCommandOptions } from './types';
|
|
9
|
+
import pkgJson from '../package.json';
|
|
10
|
+
|
|
11
|
+
throwIfNodeVersionIsNotSupported(process.versions.node, pkgJson.engines.node);
|
|
12
|
+
|
|
13
|
+
const cli = cac('create-mc-app');
|
|
14
|
+
|
|
15
|
+
// Makes the script crash on unhandled rejections instead of silently
|
|
16
|
+
// ignoring them. In the future, promise rejections that are not handled will
|
|
17
|
+
// terminate the Node.js process with a non-zero exit code.
|
|
18
|
+
process.on('unhandledRejection', (err) => {
|
|
19
|
+
throw err;
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
const run = () => {
|
|
23
|
+
// Default command
|
|
24
|
+
cli
|
|
25
|
+
.command('[project-directory]')
|
|
26
|
+
.usage(
|
|
27
|
+
'[project-directory]\n\n Bootstraps a new Custom Application project using one of the predefined templates.'
|
|
28
|
+
)
|
|
29
|
+
.option(
|
|
30
|
+
'--template <name>',
|
|
31
|
+
'(optional) The name of the template to install.',
|
|
32
|
+
{ default: 'starter' }
|
|
33
|
+
)
|
|
34
|
+
.option(
|
|
35
|
+
'--template-version <version>',
|
|
36
|
+
'(optional) The version of the template to install (either a git tag or a git branch of the "commercetools/merchant-center-application-kit" repository).',
|
|
37
|
+
{ default: 'main' }
|
|
38
|
+
)
|
|
39
|
+
.option(
|
|
40
|
+
'--skip-install',
|
|
41
|
+
'(optional) Skip installing the dependencies after cloning the template.',
|
|
42
|
+
{ default: false }
|
|
43
|
+
)
|
|
44
|
+
.option(
|
|
45
|
+
'--yes',
|
|
46
|
+
'(optional) If set, the prompt options with default values will be skipped.',
|
|
47
|
+
{ default: false }
|
|
48
|
+
)
|
|
49
|
+
.option(
|
|
50
|
+
'--entry-point-uri-path <value>',
|
|
51
|
+
'(optional) The version of the template to install. (default: starter-<hash>)'
|
|
52
|
+
)
|
|
53
|
+
.option(
|
|
54
|
+
'--initial-project-key <value>',
|
|
55
|
+
'(optional) A commercetools project key used for the initial login in development. By default, the value is prompted in the terminal.'
|
|
56
|
+
)
|
|
57
|
+
.action(async (projectDirectory, options: TCliCommandOptions) => {
|
|
58
|
+
if (!projectDirectory) {
|
|
59
|
+
cli.outputHelp();
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
await hintOutdatedVersion(pkgJson.version);
|
|
64
|
+
|
|
65
|
+
console.log('');
|
|
66
|
+
console.log(
|
|
67
|
+
`Documentation available at https://docs.commercetools.com/custom-applications`
|
|
68
|
+
);
|
|
69
|
+
console.log('');
|
|
70
|
+
|
|
71
|
+
const taskOptions = await processOptions(projectDirectory, options);
|
|
72
|
+
|
|
73
|
+
const taskList = new Listr(
|
|
74
|
+
[
|
|
75
|
+
tasks.downloadTemplate(taskOptions),
|
|
76
|
+
tasks.updatePackageJson(taskOptions),
|
|
77
|
+
tasks.updateCustomApplicationConfig(taskOptions),
|
|
78
|
+
tasks.updateApplicationConstants(taskOptions),
|
|
79
|
+
!options.skipInstall && tasks.installDependencies(taskOptions),
|
|
80
|
+
].filter(Boolean) as ListrTask[]
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
await taskList.run();
|
|
84
|
+
const useYarn = shouldUseYarn();
|
|
85
|
+
|
|
86
|
+
console.log('');
|
|
87
|
+
console.log(
|
|
88
|
+
`🎉 🎉 🎉 The Custom Application has been created in the "${taskOptions.projectDirectoryName}" folder.`
|
|
89
|
+
);
|
|
90
|
+
console.log('');
|
|
91
|
+
console.log(`To get started:`);
|
|
92
|
+
console.log(`$ cd ${taskOptions.projectDirectoryName}`);
|
|
93
|
+
if (options.skipInstall) {
|
|
94
|
+
console.log(`$ ${useYarn ? 'yarn' : 'npm'} install`);
|
|
95
|
+
}
|
|
96
|
+
console.log(`$ ${useYarn ? 'yarn' : 'npm'} start`);
|
|
97
|
+
console.log('');
|
|
98
|
+
console.log(
|
|
99
|
+
`Visit https://docs.commercetools.com/custom-applications for more info about developing Custom Applications. Enjoy 🚀`
|
|
100
|
+
);
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
cli.help();
|
|
104
|
+
cli.version(pkgJson.version);
|
|
105
|
+
|
|
106
|
+
cli.parse();
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
export default run;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import semver from 'semver';
|
|
2
|
+
import execa from 'execa';
|
|
3
|
+
|
|
4
|
+
async function hintOutdatedVersion(currentVersion: string) {
|
|
5
|
+
try {
|
|
6
|
+
const commandResult = await execa.command(
|
|
7
|
+
'npm view @commercetools-frontend/create-mc-app --json',
|
|
8
|
+
{ encoding: 'utf-8' }
|
|
9
|
+
);
|
|
10
|
+
|
|
11
|
+
const packageInfoForTagLatest = JSON.parse(commandResult.stdout);
|
|
12
|
+
|
|
13
|
+
const hasBeenReleastedInLatestTag = semver.gt(
|
|
14
|
+
packageInfoForTagLatest.version,
|
|
15
|
+
currentVersion
|
|
16
|
+
);
|
|
17
|
+
|
|
18
|
+
const hintNewerVersions = [
|
|
19
|
+
hasBeenReleastedInLatestTag && `${packageInfoForTagLatest.version}`,
|
|
20
|
+
]
|
|
21
|
+
.filter(Boolean)
|
|
22
|
+
.join(', ');
|
|
23
|
+
|
|
24
|
+
if (hintNewerVersions.length > 0) {
|
|
25
|
+
console.log('');
|
|
26
|
+
console.log(
|
|
27
|
+
`New version available! ${currentVersion} -> ${hintNewerVersions}`
|
|
28
|
+
);
|
|
29
|
+
console.log('');
|
|
30
|
+
}
|
|
31
|
+
} catch (error) {
|
|
32
|
+
// Ignore errors, as this function should not affect the exit code of the command
|
|
33
|
+
if (process.env.NODE_ENV === 'test') {
|
|
34
|
+
console.error(error);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export default hintOutdatedVersion;
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import readline, { type Interface } from 'readline';
|
|
3
|
+
import crypto from 'crypto';
|
|
4
|
+
import {
|
|
5
|
+
throwIfTemplateIsNotSupported,
|
|
6
|
+
throwIfProjectDirectoryExists,
|
|
7
|
+
throwIfInitialProjectKeyIsMissing,
|
|
8
|
+
} from './validations';
|
|
9
|
+
import { isSemVer } from './utils';
|
|
10
|
+
import type { TCliCommandOptions, TCliTaskOptions } from './types';
|
|
11
|
+
|
|
12
|
+
const question = (rl: Interface, value: string) =>
|
|
13
|
+
new Promise<string>((resolve) => rl.question(value, resolve));
|
|
14
|
+
|
|
15
|
+
const getEntryPointUriPath = async (
|
|
16
|
+
rl: Interface,
|
|
17
|
+
options: TCliCommandOptions
|
|
18
|
+
) => {
|
|
19
|
+
if (options.entryPointUriPath) {
|
|
20
|
+
return options.entryPointUriPath;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const randomEntryPointUriPath = `${options.template}-${crypto
|
|
24
|
+
.randomBytes(3)
|
|
25
|
+
.toString('hex')}`;
|
|
26
|
+
|
|
27
|
+
if (options.yes) {
|
|
28
|
+
return randomEntryPointUriPath;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const answerEntryPointUriPath = await question(
|
|
32
|
+
rl,
|
|
33
|
+
`Provide the Custom Application entryPointUriPath (default "${randomEntryPointUriPath}"): `
|
|
34
|
+
);
|
|
35
|
+
return answerEntryPointUriPath || randomEntryPointUriPath;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const getInitialProjectKey = async (
|
|
39
|
+
rl: Interface,
|
|
40
|
+
options: TCliCommandOptions
|
|
41
|
+
) => {
|
|
42
|
+
if (options.initialProjectKey) {
|
|
43
|
+
return options.initialProjectKey;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const initialProjectKey = await question(
|
|
47
|
+
rl,
|
|
48
|
+
`Provide the initial project key for local development: `
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
throwIfInitialProjectKeyIsMissing(initialProjectKey);
|
|
52
|
+
|
|
53
|
+
return initialProjectKey;
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
async function processOptions(
|
|
57
|
+
projectDirectoryName: string,
|
|
58
|
+
options: TCliCommandOptions
|
|
59
|
+
): Promise<TCliTaskOptions> {
|
|
60
|
+
if (!projectDirectoryName) {
|
|
61
|
+
throw new Error('Missing required argument "[project-directory]"');
|
|
62
|
+
}
|
|
63
|
+
const projectDirectoryPath = path.resolve(projectDirectoryName);
|
|
64
|
+
|
|
65
|
+
// Parse options
|
|
66
|
+
let tagOrBranchVersion = options.templateVersion || 'main';
|
|
67
|
+
tagOrBranchVersion =
|
|
68
|
+
isSemVer(tagOrBranchVersion) && !tagOrBranchVersion.startsWith('v')
|
|
69
|
+
? `v${tagOrBranchVersion}`
|
|
70
|
+
: tagOrBranchVersion;
|
|
71
|
+
|
|
72
|
+
const templateName = options.template;
|
|
73
|
+
|
|
74
|
+
// Validate options
|
|
75
|
+
throwIfProjectDirectoryExists(projectDirectoryName, projectDirectoryPath);
|
|
76
|
+
throwIfTemplateIsNotSupported(templateName);
|
|
77
|
+
|
|
78
|
+
// Read prompts
|
|
79
|
+
const rl = readline.createInterface({
|
|
80
|
+
input: process.stdin,
|
|
81
|
+
output: process.stdout,
|
|
82
|
+
});
|
|
83
|
+
const entryPointUriPath = await getEntryPointUriPath(rl, options);
|
|
84
|
+
const initialProjectKey = await getInitialProjectKey(rl, options);
|
|
85
|
+
rl.close();
|
|
86
|
+
|
|
87
|
+
return {
|
|
88
|
+
projectDirectoryName,
|
|
89
|
+
projectDirectoryPath,
|
|
90
|
+
templateName,
|
|
91
|
+
tagOrBranchVersion,
|
|
92
|
+
entryPointUriPath,
|
|
93
|
+
initialProjectKey,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export default processOptions;
|
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import os from 'os';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import execa from 'execa';
|
|
5
|
+
import { Listr, type ListrTask } from 'listr2';
|
|
6
|
+
import { throwIfTemplateVersionDoesNotExist } from '../validations';
|
|
7
|
+
import type { TCliTaskOptions } from '../types';
|
|
7
8
|
|
|
8
9
|
const filesToBeRemoved = ['CHANGELOG.md'];
|
|
9
10
|
|
|
10
|
-
|
|
11
|
+
function downloadTemplate(options: TCliTaskOptions): ListrTask {
|
|
11
12
|
return {
|
|
12
13
|
title: 'Downloading template',
|
|
13
14
|
task: () => {
|
|
@@ -121,4 +122,6 @@ module.exports = function downloadTemplate(options) {
|
|
|
121
122
|
]);
|
|
122
123
|
},
|
|
123
124
|
};
|
|
124
|
-
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export default downloadTemplate;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { default as downloadTemplate } from './download-template';
|
|
2
|
+
export { default as installDependencies } from './install-dependencies';
|
|
3
|
+
export { default as updatePackageJson } from './update-package-json';
|
|
4
|
+
export { default as updateCustomApplicationConfig } from './update-custom-application-config';
|
|
5
|
+
export { default as updateApplicationConstants } from './update-application-constants';
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import execa from 'execa';
|
|
2
|
+
import type { ListrTask } from 'listr2';
|
|
3
|
+
import { shouldUseYarn } from '../utils';
|
|
4
|
+
import type { TCliTaskOptions } from '../types';
|
|
3
5
|
|
|
4
|
-
|
|
6
|
+
function installDependencies(options: TCliTaskOptions): ListrTask {
|
|
5
7
|
return {
|
|
6
8
|
title: 'Installing dependencies (this might take a while)',
|
|
7
9
|
task: () => {
|
|
@@ -15,4 +17,6 @@ module.exports = function installDependencies(options) {
|
|
|
15
17
|
});
|
|
16
18
|
},
|
|
17
19
|
};
|
|
18
|
-
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export default installDependencies;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import os from 'os';
|
|
2
|
+
import fs from 'fs';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
// @ts-ignore
|
|
5
|
+
import rcfile from 'rcfile';
|
|
6
|
+
import prettier from 'prettier';
|
|
7
|
+
import { type PluginItem, transformFileSync, types } from '@babel/core';
|
|
8
|
+
import type { ListrTask } from 'listr2';
|
|
9
|
+
import { resolveFilePathByExtension } from '../utils';
|
|
10
|
+
import type { TCliTaskOptions } from '../types';
|
|
11
|
+
|
|
12
|
+
function replaceEntryPointUriPathInConstants(
|
|
13
|
+
filePath: string,
|
|
14
|
+
options: TCliTaskOptions
|
|
15
|
+
) {
|
|
16
|
+
const result = transformFileSync(filePath, {
|
|
17
|
+
plugins: [
|
|
18
|
+
function replaceConstants(): PluginItem {
|
|
19
|
+
return {
|
|
20
|
+
visitor: {
|
|
21
|
+
VariableDeclarator(nodePath) {
|
|
22
|
+
if (
|
|
23
|
+
nodePath.node.id.type === 'Identifier' &&
|
|
24
|
+
nodePath.node.id.name === 'entryPointUriPath'
|
|
25
|
+
) {
|
|
26
|
+
nodePath.node.init = types.stringLiteral(
|
|
27
|
+
options.entryPointUriPath
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
},
|
|
34
|
+
],
|
|
35
|
+
retainLines: true,
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
if (result?.code) {
|
|
39
|
+
const prettierConfig = rcfile('prettier', {
|
|
40
|
+
cwd: options.projectDirectoryPath,
|
|
41
|
+
});
|
|
42
|
+
const formattedData = prettier.format(result.code + os.EOL, prettierConfig);
|
|
43
|
+
fs.writeFileSync(filePath, formattedData, {
|
|
44
|
+
encoding: 'utf8',
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function updateApplicationConstants(options: TCliTaskOptions): ListrTask {
|
|
50
|
+
return {
|
|
51
|
+
title: 'Updating application constants',
|
|
52
|
+
task: () => {
|
|
53
|
+
const applicationConstantsPath = resolveFilePathByExtension(
|
|
54
|
+
path.join(options.projectDirectoryPath, 'src/constants')
|
|
55
|
+
);
|
|
56
|
+
replaceEntryPointUriPathInConstants(applicationConstantsPath, options);
|
|
57
|
+
},
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export default updateApplicationConstants;
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import os from 'os';
|
|
2
|
+
import fs from 'fs';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
// @ts-ignore
|
|
5
|
+
import rcfile from 'rcfile';
|
|
6
|
+
import prettier from 'prettier';
|
|
7
|
+
import { transformFileSync, types, type PluginItem } from '@babel/core';
|
|
8
|
+
import type { ListrTask } from 'listr2';
|
|
9
|
+
import { wordify, resolveFilePathByExtension } from '../utils';
|
|
10
|
+
import type { TCliTaskOptions } from '../types';
|
|
11
|
+
|
|
12
|
+
function replaceApplicationInfoInCustomApplicationConfig(
|
|
13
|
+
filePath: string,
|
|
14
|
+
options: TCliTaskOptions
|
|
15
|
+
) {
|
|
16
|
+
const appName = wordify(options.entryPointUriPath);
|
|
17
|
+
|
|
18
|
+
const result = transformFileSync(filePath, {
|
|
19
|
+
plugins: [
|
|
20
|
+
function replaceCustomApplicationConfig(): PluginItem {
|
|
21
|
+
return {
|
|
22
|
+
visitor: {
|
|
23
|
+
Identifier(nodePath) {
|
|
24
|
+
if (
|
|
25
|
+
nodePath.isIdentifier({ name: 'name' }) &&
|
|
26
|
+
nodePath.parent.type === 'ObjectProperty'
|
|
27
|
+
) {
|
|
28
|
+
nodePath.parent.value = types.stringLiteral(appName);
|
|
29
|
+
}
|
|
30
|
+
if (
|
|
31
|
+
nodePath.isIdentifier({ name: 'initialProjectKey' }) &&
|
|
32
|
+
nodePath.parent.type === 'ObjectProperty'
|
|
33
|
+
) {
|
|
34
|
+
nodePath.parent.value = types.stringLiteral(
|
|
35
|
+
options.initialProjectKey
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
if (nodePath.isIdentifier({ name: 'defaultLabel' })) {
|
|
39
|
+
const isMainMenuLinkParent = nodePath.findParent((parentPath) =>
|
|
40
|
+
parentPath.isIdentifier({
|
|
41
|
+
name: 'mainMenuLink',
|
|
42
|
+
})
|
|
43
|
+
);
|
|
44
|
+
if (
|
|
45
|
+
isMainMenuLinkParent &&
|
|
46
|
+
nodePath.parent.type === 'ObjectProperty'
|
|
47
|
+
) {
|
|
48
|
+
nodePath.parent.value = types.stringLiteral(appName);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
},
|
|
55
|
+
],
|
|
56
|
+
retainLines: true,
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
if (result?.code) {
|
|
60
|
+
const prettierConfig = rcfile('prettier', {
|
|
61
|
+
cwd: options.projectDirectoryPath,
|
|
62
|
+
});
|
|
63
|
+
const formattedData = prettier.format(result.code + os.EOL, prettierConfig);
|
|
64
|
+
fs.writeFileSync(filePath, formattedData, {
|
|
65
|
+
encoding: 'utf8',
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function updateCustomApplicationConfig(options: TCliTaskOptions): ListrTask {
|
|
71
|
+
return {
|
|
72
|
+
title: 'Updating Custom Applications config',
|
|
73
|
+
task: () => {
|
|
74
|
+
const customApplicationConfigPath = resolveFilePathByExtension(
|
|
75
|
+
path.join(options.projectDirectoryPath, 'custom-application-config')
|
|
76
|
+
);
|
|
77
|
+
replaceApplicationInfoInCustomApplicationConfig(
|
|
78
|
+
customApplicationConfigPath,
|
|
79
|
+
options
|
|
80
|
+
);
|
|
81
|
+
},
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export default updateCustomApplicationConfig;
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import os from 'os';
|
|
2
|
+
import fs from 'fs';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import type { ListrTask } from 'listr2';
|
|
5
|
+
import { slugify } from '../utils';
|
|
6
|
+
import type { TCliTaskOptions } from '../types';
|
|
5
7
|
|
|
6
|
-
|
|
8
|
+
function updatePackageJson(options: TCliTaskOptions): ListrTask {
|
|
7
9
|
return {
|
|
8
10
|
title: 'Updating package.json',
|
|
9
11
|
task: () => {
|
|
@@ -32,4 +34,6 @@ module.exports = function updatePackageJson(options) {
|
|
|
32
34
|
);
|
|
33
35
|
},
|
|
34
36
|
};
|
|
35
|
-
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export default updatePackageJson;
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export type TCliGlobalOptions = {
|
|
2
|
+
'--'?: string[];
|
|
3
|
+
};
|
|
4
|
+
|
|
5
|
+
export type TCliCommandOptions = {
|
|
6
|
+
template: 'starter' | 'starter-typescript';
|
|
7
|
+
templateVersion: string;
|
|
8
|
+
skipInstall: boolean;
|
|
9
|
+
yes: boolean;
|
|
10
|
+
entryPointUriPath?: string;
|
|
11
|
+
initialProjectKey?: string;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export type TCliTaskOptions = {
|
|
15
|
+
projectDirectoryName: string;
|
|
16
|
+
projectDirectoryPath: string;
|
|
17
|
+
templateName: TCliCommandOptions['template'];
|
|
18
|
+
tagOrBranchVersion: string;
|
|
19
|
+
entryPointUriPath: string;
|
|
20
|
+
initialProjectKey: string;
|
|
21
|
+
};
|
package/src/utils.ts
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import execa from 'execa';
|
|
3
|
+
|
|
4
|
+
const isSemVer = (version: string) => /^(v?)([0-9].[0-9].[0-9])+/.test(version);
|
|
5
|
+
|
|
6
|
+
const shouldUseYarn = () => {
|
|
7
|
+
try {
|
|
8
|
+
const result = execa.commandSync('yarn --version', { stdio: 'ignore' });
|
|
9
|
+
return !result.failed;
|
|
10
|
+
} catch (error) {
|
|
11
|
+
return false;
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
const slugify = (name: string) => name.toLowerCase().replace(/_/gi, '-');
|
|
16
|
+
|
|
17
|
+
const upperFirst = (value: string) =>
|
|
18
|
+
value.charAt(0).toUpperCase() + value.slice(1);
|
|
19
|
+
|
|
20
|
+
const wordify = (slug: string) =>
|
|
21
|
+
slug
|
|
22
|
+
.split('-')
|
|
23
|
+
.map((word) => upperFirst(word))
|
|
24
|
+
.join(' ');
|
|
25
|
+
|
|
26
|
+
const resolveFilePathByExtension = (requestedModule: string) => {
|
|
27
|
+
const fileExtension = ['.js', '.ts', '.mjs', '.cjs'].find((ext) => {
|
|
28
|
+
const filePath = `${requestedModule}${ext}`;
|
|
29
|
+
return fs.existsSync(filePath);
|
|
30
|
+
});
|
|
31
|
+
return `${requestedModule}${fileExtension}`;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export {
|
|
35
|
+
isSemVer,
|
|
36
|
+
shouldUseYarn,
|
|
37
|
+
slugify,
|
|
38
|
+
wordify,
|
|
39
|
+
upperFirst,
|
|
40
|
+
resolveFilePathByExtension,
|
|
41
|
+
};
|