@cbs-consulting/generator-btp 1.0.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/README.md +105 -0
- package/generators/app/index.js +48 -0
- package/generators/cap/additions/.vscode/extensions.json +74 -0
- package/generators/cap/additions/.vscode/settings.json +57 -0
- package/generators/cap/additions/package.json +31 -0
- package/generators/cap/dependencies.json +17 -0
- package/generators/cap/index.js +194 -0
- package/generators/cap/templates/_.devcontainer/Dockerfile +1 -0
- package/generators/cap/templates/_.devcontainer/devcontainer.json +183 -0
- package/generators/cap/templates/_.devcontainer/post-create.sh +16 -0
- package/generators/cap/templates/_.gitattributes +3 -0
- package/generators/cap/templates/_.gitconfig.aliases +16 -0
- package/generators/cap/templates/_.gitignore +48 -0
- package/generators/cap/templates/_.npmrc +1 -0
- package/generators/cap/templates/azure-pipelines.yaml +31 -0
- package/generators/cap/templates/base.tsconfig.json +14 -0
- package/generators/cap/templates/eslint.config.mjs +4 -0
- package/generators/cap/templates/mta-ext/dev.mtaext +11 -0
- package/generators/cap/templates/mta-ext/prod.mtaext +11 -0
- package/generators/cap/templates/mta-ext/test.mtaext +11 -0
- package/generators/cap/templates/mta.yaml +207 -0
- package/generators/cap/templates/prettier.config.mjs +2 -0
- package/generators/ui5/additions/package.json +9 -0
- package/generators/ui5/additions/tsconfig.json +6 -0
- package/generators/ui5/dependencies.json +9 -0
- package/generators/ui5/index.js +120 -0
- package/generators/ui5/templates/eslint.config.mjs +2 -0
- package/generators/ui5/templates/ui5lint.config.mjs +2 -0
- package/package.json +42 -0
- package/utils/jsonFile.js +37 -0
package/README.md
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# CAP/UI5 Foundation Generator
|
|
2
|
+
|
|
3
|
+
A Yeoman generator for creating the foundation of CAP/UI5 projects with TypeScript, ESLint, Prettier, and other essential development configurations.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
This generator sets up a solid foundation for your CAP/UI5 projects with:
|
|
8
|
+
|
|
9
|
+
- ✅ **TypeScript** - Full TypeScript configuration with strict settings
|
|
10
|
+
- ✅ **ESLint** - Code quality and linting rules optimized for TypeScript
|
|
11
|
+
- ✅ **Prettier** - Consistent code formatting
|
|
12
|
+
- ✅ **Husky** - Git hooks for pre-commit quality checks
|
|
13
|
+
- ✅ **Jest** - Testing framework with TypeScript support
|
|
14
|
+
- ✅ **GitHub Actions** - CI/CD pipeline for automated testing and building
|
|
15
|
+
- ✅ **VS Code** - Optimized settings and recommended extensions
|
|
16
|
+
- ✅ **Docker** - Container configuration for deployment (optional)
|
|
17
|
+
|
|
18
|
+
## Installation
|
|
19
|
+
|
|
20
|
+
First, install Yeoman and this generator globally:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
npm install -g yo
|
|
24
|
+
npm install -g @cbs-consulting/generator-btp
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Or install locally in your project:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
npm install --save-dev @cbs-consulting/generator-btp
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Usage
|
|
34
|
+
|
|
35
|
+
This generator is split into two sub-generators.
|
|
36
|
+
|
|
37
|
+
1. CAP flow
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
mkdir my-cap
|
|
41
|
+
cd my-cap
|
|
42
|
+
yo @cbs-consulting/btp:cap
|
|
43
|
+
# read and execute the printed steps shown in the terminal
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
2. UI5 flow
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
mkdir my-ui5
|
|
50
|
+
cd my-ui5
|
|
51
|
+
# ensure you have a UI5 project skeleton (or after cds init)
|
|
52
|
+
yo @cbs-consulting/btp:ui5
|
|
53
|
+
# read and execute the printed steps in the terminal
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
The CAP sub-generator copies all templates from generators/app/templatesCAP into your project and merges additions from generators/app/additionsCAP into existing files. The scripting.txt is shown but not executed automatically.
|
|
57
|
+
|
|
58
|
+
## Generated Project Structure
|
|
59
|
+
|
|
60
|
+
```
|
|
61
|
+
my-project/
|
|
62
|
+
├── src/ # Source TypeScript files
|
|
63
|
+
├── tests/ # Test files (if Jest is selected)
|
|
64
|
+
├── dist/ # Compiled output (after build)
|
|
65
|
+
├── .github/workflows/ # GitHub Actions CI/CD (if selected)
|
|
66
|
+
├── .vscode/ # VS Code settings (if selected)
|
|
67
|
+
├── .eslintrc.js # ESLint configuration
|
|
68
|
+
├── .prettierrc # Prettier configuration
|
|
69
|
+
├── .gitignore # Git ignore rules
|
|
70
|
+
├── tsconfig.json # TypeScript configuration
|
|
71
|
+
├── jest.config.js # Jest configuration (if selected)
|
|
72
|
+
├── package.json # Project dependencies and scripts
|
|
73
|
+
└── README.md # Project documentation
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Available Scripts
|
|
77
|
+
|
|
78
|
+
The generated project includes these npm scripts:
|
|
79
|
+
|
|
80
|
+
- `npm run build` - Compile TypeScript to JavaScript
|
|
81
|
+
- `npm run build:watch` - Watch mode compilation
|
|
82
|
+
- `npm run lint` - Run ESLint on your code
|
|
83
|
+
- `npm run lint:fix` - Fix auto-fixable ESLint issues
|
|
84
|
+
- `npm run format` - Format code with Prettier
|
|
85
|
+
- `npm run format:check` - Check if code is properly formatted
|
|
86
|
+
- `npm test` - Run Jest tests (if enabled)
|
|
87
|
+
- `npm run test:watch` - Run tests in watch mode
|
|
88
|
+
- `npm run test:coverage` - Generate test coverage report
|
|
89
|
+
|
|
90
|
+
## Development
|
|
91
|
+
|
|
92
|
+
To develop this generator locally:
|
|
93
|
+
|
|
94
|
+
1. Clone this repository
|
|
95
|
+
2. Install dependencies: `npm install`
|
|
96
|
+
3. Link the generator: `npm link`
|
|
97
|
+
4. Test in a new directory: `yo @cbs-consulting/btp`
|
|
98
|
+
|
|
99
|
+
## Contributing
|
|
100
|
+
|
|
101
|
+
1. Fork the repository
|
|
102
|
+
2. Create a feature branch
|
|
103
|
+
3. Make your changes
|
|
104
|
+
4. Add tests if applicable
|
|
105
|
+
5. Submit a pull request
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
const Generator = require("yeoman-generator");
|
|
2
|
+
const chalk = require("chalk");
|
|
3
|
+
const yosay = require("yosay");
|
|
4
|
+
const { resolve } = require("node:path");
|
|
5
|
+
|
|
6
|
+
module.exports = class extends Generator {
|
|
7
|
+
async prompting() {
|
|
8
|
+
this.log(
|
|
9
|
+
yosay(
|
|
10
|
+
`Hey, welcome to the ${chalk.hex("e38330")("@cbs-consulting/generator-btp")}. I'm pretty sure, you will love me!`,
|
|
11
|
+
),
|
|
12
|
+
);
|
|
13
|
+
|
|
14
|
+
const { kind } = await this.prompt([
|
|
15
|
+
{
|
|
16
|
+
type: "list",
|
|
17
|
+
name: "kind",
|
|
18
|
+
message: "What do you want to do?",
|
|
19
|
+
choices: [
|
|
20
|
+
{
|
|
21
|
+
name: "Bootstrap a new CAP project",
|
|
22
|
+
value: "cap",
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
name: "Add best practices to existing UI5 project",
|
|
26
|
+
value: "ui5",
|
|
27
|
+
},
|
|
28
|
+
],
|
|
29
|
+
},
|
|
30
|
+
]);
|
|
31
|
+
|
|
32
|
+
this.kind = kind;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
writing() {
|
|
36
|
+
if (this.kind === "cap") {
|
|
37
|
+
this.composeWith(resolve(__dirname, "../cap/index.js"));
|
|
38
|
+
} else if (this.kind === "ui5") {
|
|
39
|
+
this.composeWith(resolve(__dirname, "../ui5/index.js"));
|
|
40
|
+
} else {
|
|
41
|
+
this.log(chalk.red("Unknown selection"));
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
end() {
|
|
46
|
+
this.log(chalk.green("Done."));
|
|
47
|
+
}
|
|
48
|
+
};
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
{
|
|
2
|
+
"recommendations": [
|
|
3
|
+
// GitHub Copilot
|
|
4
|
+
"GitHub.copilot-chat",
|
|
5
|
+
// JavaScript/TypeScript linting
|
|
6
|
+
"dbaeumer.vscode-eslint",
|
|
7
|
+
// Code formatting
|
|
8
|
+
"esbenp.prettier-vscode",
|
|
9
|
+
// Prettify TS errors
|
|
10
|
+
"YoavBls.pretty-ts-errors",
|
|
11
|
+
// CSV Editing
|
|
12
|
+
"janisdd.vscode-edit-csv",
|
|
13
|
+
// English spell checking
|
|
14
|
+
"streetsidesoftware.code-spell-checker",
|
|
15
|
+
// German spell checking
|
|
16
|
+
"streetsidesoftware.code-spell-checker-german",
|
|
17
|
+
// Enhanced git functionalities
|
|
18
|
+
"eamodio.gitlens",
|
|
19
|
+
// i18n tools and annotations
|
|
20
|
+
"lokalise.i18n-ally",
|
|
21
|
+
// Autocomplete path names
|
|
22
|
+
"christian-kohler.path-intellisense",
|
|
23
|
+
// XML language support
|
|
24
|
+
"redhat.vscode-xml",
|
|
25
|
+
// Markdown linting, editing and preview
|
|
26
|
+
"DavidAnson.vscode-markdownlint",
|
|
27
|
+
"yzhang.markdown-all-in-one",
|
|
28
|
+
"shd101wyy.markdown-preview-enhanced",
|
|
29
|
+
|
|
30
|
+
// easy switch between projects
|
|
31
|
+
"alefragnani.project-manager",
|
|
32
|
+
// resource monitor
|
|
33
|
+
"mutantdino.resourcemonitor",
|
|
34
|
+
// bookmark code places
|
|
35
|
+
"alefragnani.Bookmarks",
|
|
36
|
+
// structured view on ToDo. FixMe commandserrr
|
|
37
|
+
"Gruntfuggly.todo-tree",
|
|
38
|
+
// highlight columns in CSV, TSV
|
|
39
|
+
"mechatroner.rainbow-csv",
|
|
40
|
+
// useful for tempplate string
|
|
41
|
+
"meganrogge.template-string-converter",
|
|
42
|
+
// display errors inline
|
|
43
|
+
"usernamehw.errorlens",
|
|
44
|
+
//live share VS code
|
|
45
|
+
"MS-vsliveshare.vsliveshare",
|
|
46
|
+
// show package.json dependencies updates
|
|
47
|
+
"codeandstuff.package-json-upgrade",
|
|
48
|
+
|
|
49
|
+
// ====================
|
|
50
|
+
// CAP
|
|
51
|
+
// ====================
|
|
52
|
+
// SAP CDS language support
|
|
53
|
+
"SAPSE.vscode-cds",
|
|
54
|
+
// SQLite database viewer
|
|
55
|
+
"qwtel.sqlite-viewer",
|
|
56
|
+
// REST API testing
|
|
57
|
+
"humao.rest-client",
|
|
58
|
+
|
|
59
|
+
// ====================
|
|
60
|
+
// UI5 / Fiori
|
|
61
|
+
// ====================
|
|
62
|
+
// Auto Renaming e.g. XML tags
|
|
63
|
+
"formulahendry.auto-rename-tag",
|
|
64
|
+
// Multiple Fiori Tools
|
|
65
|
+
"SAPSE.sap-ux-fiori-tools-extension-pack",
|
|
66
|
+
|
|
67
|
+
// ====================
|
|
68
|
+
// Tasks
|
|
69
|
+
// ====================
|
|
70
|
+
// Better variables in tasks
|
|
71
|
+
"rioj7.command-variable"
|
|
72
|
+
],
|
|
73
|
+
"unwantedRecommendations": []
|
|
74
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
{
|
|
2
|
+
// ====================
|
|
3
|
+
// Editor
|
|
4
|
+
// ====================
|
|
5
|
+
"editor.formatOnSave": true,
|
|
6
|
+
"editor.formatOnPaste": true,
|
|
7
|
+
"editor.codeActionsOnSave": {
|
|
8
|
+
"source.fixAll.eslint": "always"
|
|
9
|
+
},
|
|
10
|
+
"editor.rulers": [80],
|
|
11
|
+
"editor.minimap.renderCharacters": false, // Small performance boost
|
|
12
|
+
"workbench.startupEditor": "none",
|
|
13
|
+
|
|
14
|
+
// Automatically update import paths when files are moved or renamed
|
|
15
|
+
"typescript.updateImportsOnFileMove.enabled": "always",
|
|
16
|
+
"javascript.updateImportsOnFileMove.enabled": "always",
|
|
17
|
+
|
|
18
|
+
// Default formatters for specific file types
|
|
19
|
+
"[cds]": {
|
|
20
|
+
"editor.defaultFormatter": "SAPSE.vscode-cds"
|
|
21
|
+
},
|
|
22
|
+
"[markdown]": {
|
|
23
|
+
"editor.defaultFormatter": "yzhang.markdown-all-in-one"
|
|
24
|
+
},
|
|
25
|
+
"[javascript][typescript][json][typescriptreact]": {
|
|
26
|
+
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
|
27
|
+
},
|
|
28
|
+
|
|
29
|
+
// ====================
|
|
30
|
+
// Extensions
|
|
31
|
+
// ====================
|
|
32
|
+
"extensions.ignoreRecommendations": true,
|
|
33
|
+
"github.copilot.nextEditSuggestions.enabled": true,
|
|
34
|
+
"gitlens.hovers.currentLine.over": "line",
|
|
35
|
+
"i18n-ally.displayLanguage": "de",
|
|
36
|
+
"i18n-ally.enabledFrameworks": ["ui5"],
|
|
37
|
+
"i18n-ally.keystyle": "flat",
|
|
38
|
+
"i18n-ally.localesPaths": ["i18n", "webapp/i18n"],
|
|
39
|
+
"i18n-ally.sourceLanguage": "de",
|
|
40
|
+
// Usage pattern for i18n keys in translation function t('key')
|
|
41
|
+
"i18n-ally.regex.usageMatchAppend": ["\\bt\\(['\"`]({key})['\"`]\\)"],
|
|
42
|
+
|
|
43
|
+
// ====================
|
|
44
|
+
// Scripts
|
|
45
|
+
// ====================
|
|
46
|
+
"npm.scriptRunner": "node",
|
|
47
|
+
|
|
48
|
+
// ====================
|
|
49
|
+
// Git
|
|
50
|
+
// ====================
|
|
51
|
+
"git.openRepositoryInParentFolders": "always",
|
|
52
|
+
|
|
53
|
+
// ====================
|
|
54
|
+
// Quality
|
|
55
|
+
// ====================
|
|
56
|
+
"cSpell.language": "en,de-DE"
|
|
57
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"scripts": {
|
|
3
|
+
"format": "prettier --write \"**/*.(ts|js|json|yml|yaml|xml)\"",
|
|
4
|
+
"lint": "eslint .",
|
|
5
|
+
"lint-fix": "eslint . --fix",
|
|
6
|
+
"lint-quiet": "eslint . --quiet",
|
|
7
|
+
"test": "CDS_TYPESCRIPT='true' jest",
|
|
8
|
+
"build": "rm -rf resources mta_archives dist gen && npx -p @sap/cds-dk cds build --production",
|
|
9
|
+
"deploy-dev": "npm run build && mbt build --mtar archive.mtar && cf deploy mta_archives/archive.mtar -e mta-ext/dev.mtaext --strategy blue-green --skip-testing-phase --skip-idle-start --abort-on-error",
|
|
10
|
+
"coverage-report": "npx serve coverage/lcov-report",
|
|
11
|
+
"git-config": "git config --local include.path ../.gitconfig.aliases",
|
|
12
|
+
"check-deps": "ncu",
|
|
13
|
+
"upgrade-deps": "ncu -u"
|
|
14
|
+
},
|
|
15
|
+
"simple-git-hooks": {
|
|
16
|
+
"pre-commit": "npx lint-staged"
|
|
17
|
+
},
|
|
18
|
+
"lint-staged": {
|
|
19
|
+
"*.{ts,js,json,yml,yaml,xml}": "npm run format",
|
|
20
|
+
"*.{ts,js}": "npm run lint-fix"
|
|
21
|
+
},
|
|
22
|
+
"cds": {
|
|
23
|
+
"requires": {
|
|
24
|
+
"[test]": {
|
|
25
|
+
"auth": {
|
|
26
|
+
"kind": "dummy"
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"devDependencies": [
|
|
3
|
+
"cbs-tools",
|
|
4
|
+
"prettier",
|
|
5
|
+
"prettier-plugin-organize-imports",
|
|
6
|
+
"@prettier/plugin-xml",
|
|
7
|
+
"simple-git-hooks",
|
|
8
|
+
"lint-staged",
|
|
9
|
+
"eslint",
|
|
10
|
+
"typescript-eslint",
|
|
11
|
+
"eslint-config-prettier",
|
|
12
|
+
"@sap/eslint-plugin-cds@3",
|
|
13
|
+
"@cap-js/cds-test",
|
|
14
|
+
"ts-jest",
|
|
15
|
+
"npm-check-updates"
|
|
16
|
+
]
|
|
17
|
+
}
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
const chalk = require("chalk");
|
|
2
|
+
const glob = require("glob");
|
|
3
|
+
const mergewith = require("lodash.mergewith");
|
|
4
|
+
const fs = require("node:fs");
|
|
5
|
+
const { join, resolve } = require("node:path");
|
|
6
|
+
const Generator = require("yeoman-generator");
|
|
7
|
+
const {
|
|
8
|
+
mergeArray,
|
|
9
|
+
readJsonC,
|
|
10
|
+
readJsonCSafe,
|
|
11
|
+
} = require("../../utils/jsonFile");
|
|
12
|
+
const globSync = glob.globSync || glob.sync;
|
|
13
|
+
|
|
14
|
+
module.exports = class extends Generator {
|
|
15
|
+
_tplRoot = resolve(__dirname, "./templates");
|
|
16
|
+
_addRoot = resolve(__dirname, "./additions");
|
|
17
|
+
_capRoot = __dirname;
|
|
18
|
+
|
|
19
|
+
async initializing() {
|
|
20
|
+
const aPrompt = [];
|
|
21
|
+
|
|
22
|
+
aPrompt.push(
|
|
23
|
+
{
|
|
24
|
+
type: "input",
|
|
25
|
+
name: "projectName",
|
|
26
|
+
message: "Enter the project name:",
|
|
27
|
+
validate(sInput) {
|
|
28
|
+
if (sInput.length > 0) {
|
|
29
|
+
return true;
|
|
30
|
+
}
|
|
31
|
+
return "Project name must not be empty.";
|
|
32
|
+
},
|
|
33
|
+
default: "My new CAP project",
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
type: "input",
|
|
37
|
+
name: "customerName",
|
|
38
|
+
message: "Enter the customer's name:",
|
|
39
|
+
validate(sInput) {
|
|
40
|
+
if (sInput.length > 0) {
|
|
41
|
+
return true;
|
|
42
|
+
}
|
|
43
|
+
return "Customer name must not be empty.";
|
|
44
|
+
},
|
|
45
|
+
default: "My Customer",
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
type: "input",
|
|
49
|
+
name: "dbSchema",
|
|
50
|
+
message: "Enter the database schema name?",
|
|
51
|
+
validate(sInput) {
|
|
52
|
+
if (sInput.length > 0) {
|
|
53
|
+
return true;
|
|
54
|
+
}
|
|
55
|
+
return "Database schema name must not be empty.";
|
|
56
|
+
},
|
|
57
|
+
default: "MY_DB_SCHEMA",
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
type: "confirm",
|
|
61
|
+
name: "useAzureDevOps",
|
|
62
|
+
message: "Is Azure DevOps used for version control and CI/CD?",
|
|
63
|
+
default: true,
|
|
64
|
+
},
|
|
65
|
+
);
|
|
66
|
+
|
|
67
|
+
const answers = await this.prompt(aPrompt);
|
|
68
|
+
|
|
69
|
+
// Check if .git directory exists, if not run git init
|
|
70
|
+
if (!fs.existsSync(this.destinationPath(".git"))) {
|
|
71
|
+
this.log(chalk.bold("\n🔧 Initializing git repository..."));
|
|
72
|
+
this.spawnCommandSync("git", ["init"]);
|
|
73
|
+
}
|
|
74
|
+
this.destinationRoot(this.destinationPath());
|
|
75
|
+
|
|
76
|
+
this.log(chalk.bold("\n🚀 Initializing CAP project..."));
|
|
77
|
+
this.spawnCommandSync(
|
|
78
|
+
"cds",
|
|
79
|
+
[
|
|
80
|
+
"init",
|
|
81
|
+
"--add",
|
|
82
|
+
"typescript,mta,xsuaa,hana,sqlite,html5-repo,tiny-sample,http",
|
|
83
|
+
],
|
|
84
|
+
{
|
|
85
|
+
cwd: this.destinationPath(),
|
|
86
|
+
},
|
|
87
|
+
);
|
|
88
|
+
|
|
89
|
+
answers.projectNameNormalized = answers.projectName
|
|
90
|
+
.toLowerCase()
|
|
91
|
+
.replace(/\s+/g, "-");
|
|
92
|
+
answers.customerNameNormalized = answers.customerName
|
|
93
|
+
.toLowerCase()
|
|
94
|
+
.replace(/\s+/g, "-");
|
|
95
|
+
this.answers = answers;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
writing() {
|
|
99
|
+
this.log(chalk.bold("\n✍️ Writing files..."));
|
|
100
|
+
|
|
101
|
+
this.sourceRoot(join(__dirname, "templates"));
|
|
102
|
+
globSync("**", {
|
|
103
|
+
cwd: this.sourceRoot(),
|
|
104
|
+
nodir: true,
|
|
105
|
+
}).forEach((fileName) => {
|
|
106
|
+
let sOrigin;
|
|
107
|
+
let sTarget;
|
|
108
|
+
|
|
109
|
+
if (fileName === "azure-pipelines.yaml" && !this.answers.useAzureDevOps) {
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
sOrigin = this.templatePath(fileName);
|
|
114
|
+
sTarget = this.destinationPath(
|
|
115
|
+
fileName.replace(/^_/, "").replace(/\/_/, "/"),
|
|
116
|
+
);
|
|
117
|
+
|
|
118
|
+
this.fs.copyTpl(sOrigin, sTarget, this.answers);
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
// 2) Merge additions into existing files (scripting.txt is excluded by design)
|
|
122
|
+
// package.json
|
|
123
|
+
const destPkgPath = this.destinationPath("package.json");
|
|
124
|
+
const srcPkgPath = join(this._addRoot, "package.json");
|
|
125
|
+
const destPkg = readJsonCSafe(this, destPkgPath, {});
|
|
126
|
+
const addPkg = readJsonC(srcPkgPath, {});
|
|
127
|
+
const mergedPkg = mergewith({}, destPkg, addPkg, mergeArray);
|
|
128
|
+
mergedPkg.name = this.answers.projectNameNormalized;
|
|
129
|
+
this.fs.writeJSON(destPkgPath, mergedPkg);
|
|
130
|
+
|
|
131
|
+
// tsconfig.json -> ensure it extends base.tsconfig.json
|
|
132
|
+
const destTsPath = this.destinationPath("tsconfig.json");
|
|
133
|
+
const destTs = readJsonCSafe(this, destTsPath, {});
|
|
134
|
+
if (destTs.extends !== "./base.tsconfig.json") {
|
|
135
|
+
destTs.extends = "./base.tsconfig.json";
|
|
136
|
+
}
|
|
137
|
+
this.fs.writeJSON(destTsPath, destTs);
|
|
138
|
+
|
|
139
|
+
// .vscode/settings.json
|
|
140
|
+
const destVsSettingsPath = this.destinationPath(".vscode/settings.json");
|
|
141
|
+
const addVsSettingsPath = join(this._addRoot, ".vscode/settings.json");
|
|
142
|
+
const destVsSettings = readJsonCSafe(this, destVsSettingsPath, {});
|
|
143
|
+
const addVsSettings = readJsonC(addVsSettingsPath, {});
|
|
144
|
+
const mergedVsSettings = mergewith(
|
|
145
|
+
{},
|
|
146
|
+
destVsSettings,
|
|
147
|
+
addVsSettings,
|
|
148
|
+
mergeArray,
|
|
149
|
+
);
|
|
150
|
+
this.fs.writeJSON(destVsSettingsPath, mergedVsSettings);
|
|
151
|
+
|
|
152
|
+
// .vscode/extensions.json (merge arrays)
|
|
153
|
+
const destVsExtPath = this.destinationPath(".vscode/extensions.json");
|
|
154
|
+
const addVsExtPath = join(this._addRoot, ".vscode/extensions.json");
|
|
155
|
+
const destVsExt = readJsonCSafe(this, destVsExtPath, {
|
|
156
|
+
recommendations: [],
|
|
157
|
+
unwantedRecommendations: [],
|
|
158
|
+
});
|
|
159
|
+
const addVsExt = readJsonC(addVsExtPath, {
|
|
160
|
+
recommendations: [],
|
|
161
|
+
unwantedRecommendations: [],
|
|
162
|
+
});
|
|
163
|
+
const mergedVsExt = mergewith({}, destVsExt, addVsExt, mergeArray);
|
|
164
|
+
this.fs.writeJSON(destVsExtPath, mergedVsExt);
|
|
165
|
+
|
|
166
|
+
// Remove undeploy.json from db folder
|
|
167
|
+
const undeployPath = this.destinationPath("db/undeploy.json");
|
|
168
|
+
this.fs.delete(undeployPath);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
install() {
|
|
172
|
+
this.log(chalk.bold("\n📦 Installing npm dependencies..."));
|
|
173
|
+
const dependenciesPath = join(this._capRoot, "dependencies.json");
|
|
174
|
+
const dependencies = readJsonCSafe(this, dependenciesPath, {});
|
|
175
|
+
const devDeps = Array.isArray(dependencies.devDependencies)
|
|
176
|
+
? dependencies.devDependencies
|
|
177
|
+
: [];
|
|
178
|
+
if (devDeps.length > 0) {
|
|
179
|
+
this.spawnCommandSync(
|
|
180
|
+
"npm",
|
|
181
|
+
["install", "--save-dev", "--save-exact"].concat(devDeps),
|
|
182
|
+
);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
end() {
|
|
187
|
+
this.log(chalk.bold("\n🪝 Initializing simple git hooks..."));
|
|
188
|
+
this.spawnCommandSync("npx", ["simple-git-hooks"]);
|
|
189
|
+
|
|
190
|
+
this.log(chalk.bold.green("\n✅ CAP best practices applied."));
|
|
191
|
+
this.log("Next steps:");
|
|
192
|
+
this.log("1) Review/commit the changes.");
|
|
193
|
+
}
|
|
194
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
FROM cbsgroupdocker/cbs-default:latest
|