@mbc-cqrs-serverless/cli 0.1.49-beta.0 → 0.1.51-beta.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 +94 -63
- package/dist/actions/generate.action.js +44 -0
- package/dist/actions/new.action.get-package-version.spec.js +29 -0
- package/dist/actions/new.action.is-latest-version.spec.js +36 -0
- package/dist/actions/new.action.js +12 -6
- package/dist/actions/new.action.spec.js +84 -0
- package/dist/actions/new.action.update-env-local.spec.js +35 -0
- package/dist/actions/new.action.use-package-version.spec.js +46 -0
- package/dist/actions/ui.action.js +7 -5
- package/dist/commands/command.input.js +2 -0
- package/dist/commands/generate.command.js +24 -0
- package/dist/commands/index.js +2 -0
- package/dist/index.js +13 -2
- package/dist/runners/abstract.runner.js +44 -0
- package/dist/runners/schematic.runner.js +21 -0
- package/dist/schematics/collection.json +34 -0
- package/dist/schematics/index.js +17 -0
- package/dist/schematics/lib/controller/controller.factory.js +40 -0
- package/dist/schematics/lib/controller/controller.factory.spec.js +79 -0
- package/dist/schematics/lib/controller/files/__name@dasherize__.controller.ts +11 -0
- package/dist/schematics/lib/controller/schema.json +18 -0
- package/dist/schematics/lib/controller/units/__name@dasherize__.controller.__specFileSuffix__.ts +19 -0
- package/dist/schematics/lib/dto/dto.factory.js +32 -0
- package/dist/schematics/lib/dto/dto.factory.spec.js +128 -0
- package/dist/schematics/lib/dto/files/dto/__name@dasherize__-attributes.dto.ts +6 -0
- package/dist/schematics/lib/dto/files/dto/__name@dasherize__-command.dto.ts +16 -0
- package/dist/schematics/lib/dto/files/dto/__name@dasherize__-create.dto.ts +18 -0
- package/dist/schematics/lib/dto/files/dto/__name@dasherize__-search.dto.ts +2 -0
- package/dist/schematics/lib/dto/files/dto/__name@dasherize__-update.dto.ts +34 -0
- package/dist/schematics/lib/dto/schema.json +18 -0
- package/dist/schematics/lib/entity/entity.factory.js +30 -0
- package/dist/schematics/lib/entity/entity.factory.spec.js +86 -0
- package/dist/schematics/lib/entity/files/entity/__name@dasherize__-command.entity.ts +12 -0
- package/dist/schematics/lib/entity/files/entity/__name@dasherize__-data-list.entity.ts +12 -0
- package/dist/schematics/lib/entity/files/entity/__name@dasherize__-data.entity.ts +12 -0
- package/dist/schematics/lib/entity/schema.json +18 -0
- package/dist/schematics/lib/module/files/async/__name@dasherize__.controller.ts +74 -0
- package/dist/schematics/lib/module/files/async/__name@dasherize__.module.ts +19 -0
- package/dist/schematics/lib/module/files/async/__name@dasherize__.service.ts +164 -0
- package/dist/schematics/lib/module/files/async/dto/__name@dasherize__-attributes.dto.ts +6 -0
- package/dist/schematics/lib/module/files/async/dto/__name@dasherize__-command.dto.ts +16 -0
- package/dist/schematics/lib/module/files/async/dto/__name@dasherize__-create.dto.ts +18 -0
- package/dist/schematics/lib/module/files/async/dto/__name@dasherize__-search.dto.ts +2 -0
- package/dist/schematics/lib/module/files/async/dto/__name@dasherize__-update.dto.ts +34 -0
- package/dist/schematics/lib/module/files/async/entity/__name@dasherize__-command.entity.ts +12 -0
- package/dist/schematics/lib/module/files/async/entity/__name@dasherize__-data-list.entity.ts +12 -0
- package/dist/schematics/lib/module/files/async/entity/__name@dasherize__-data.entity.ts +12 -0
- package/dist/schematics/lib/module/files/async/handler/__name@dasherize__-rds.handler.ts +62 -0
- package/dist/schematics/lib/module/files/sync/__name@dasherize__.controller.ts +74 -0
- package/dist/schematics/lib/module/files/sync/__name@dasherize__.module.ts +19 -0
- package/dist/schematics/lib/module/files/sync/__name@dasherize__.service.ts +164 -0
- package/dist/schematics/lib/module/files/sync/dto/__name@dasherize__-attributes.dto.ts +6 -0
- package/dist/schematics/lib/module/files/sync/dto/__name@dasherize__-command.dto.ts +16 -0
- package/dist/schematics/lib/module/files/sync/dto/__name@dasherize__-create.dto.ts +18 -0
- package/dist/schematics/lib/module/files/sync/dto/__name@dasherize__-search.dto.ts +2 -0
- package/dist/schematics/lib/module/files/sync/dto/__name@dasherize__-update.dto.ts +34 -0
- package/dist/schematics/lib/module/files/sync/entity/__name@dasherize__-command.entity.ts +12 -0
- package/dist/schematics/lib/module/files/sync/entity/__name@dasherize__-data-list.entity.ts +12 -0
- package/dist/schematics/lib/module/files/sync/entity/__name@dasherize__-data.entity.ts +12 -0
- package/dist/schematics/lib/module/files/sync/handler/__name@dasherize__-rds.handler.ts +62 -0
- package/dist/schematics/lib/module/module.factory.js +204 -0
- package/dist/schematics/lib/module/module.factory.spec.js +188 -0
- package/dist/schematics/lib/module/schema.json +28 -0
- package/dist/schematics/lib/module/units/__name@dasherize__.controller.__specFileSuffix__.ts +19 -0
- package/dist/schematics/lib/module/units/__name@dasherize__.service.__specFileSuffix__.ts +19 -0
- package/dist/schematics/lib/service/files/__name@dasherize__.service.ts +12 -0
- package/dist/schematics/lib/service/schema.json +18 -0
- package/dist/schematics/lib/service/service.factory.js +40 -0
- package/dist/schematics/lib/service/service.factory.spec.js +81 -0
- package/dist/schematics/lib/service/units/__name@dasherize__.service.__specFileSuffix__.ts +19 -0
- package/dist/schematics/schematic.colection.js +60 -0
- package/dist/schematics/schematic.option.js +44 -0
- package/dist/schematics/utils/check-files-exist.js +13 -0
- package/dist/schematics/utils/index.js +17 -0
- package/dist/ui/index.js +18 -0
- package/dist/ui/logger.js +54 -0
- package/dist/ui/message.js +6 -0
- package/dist/utils/formatting.js +18 -0
- package/dist/utils/index.js +18 -0
- package/dist/utils/local-binaries.js +20 -0
- package/package.json +14 -5
- package/templates/.env.local +1 -1
- package/templates/README.md +1 -1
- package/templates/infra/README.md +6 -1
- package/templates/infra/libs/infra-stack.ts +1 -1
- package/templates/infra-local/docker-compose.yml +1 -1
- package/templates/infra-local/serverless.yml +19 -21
- package/templates/infra-local/swagger.json +396 -0
- package/templates/package.json +1 -0
- package/templates/prisma/dynamodbs/cqrs.json +1 -1
- package/templates/prisma/schema.prisma +4 -7
- package/templates/src/helpers/id.ts +12 -0
- package/templates/src/helpers/index.ts +1 -0
- package/templates/src/main.module.ts +2 -2
- package/templates/src/{master/dto/master-attributes.dto.ts → sample/dto/sample-attributes.dto.ts} +2 -2
- package/templates/src/{master/dto/master-command.dto.ts → sample/dto/sample-command.dto.ts} +4 -4
- package/templates/src/sample/entity/sample-command.entity.ts +13 -0
- package/templates/src/sample/entity/sample-data-list.entity.ts +13 -0
- package/templates/src/sample/entity/sample-data.entity.ts +13 -0
- package/templates/src/{master/handler/master-rds.handler.ts → sample/handler/sample-rds.handler.ts} +5 -7
- package/templates/src/{master/master.controller.ts → sample/sample.controller.ts} +22 -22
- package/templates/src/sample/sample.module.ts +19 -0
- package/templates/src/{master/master.service.ts → sample/sample.service.ts} +12 -12
- package/templates/test/api.http +25 -0
- package/templates/tsconfig.json +1 -1
- package/templates/src/master/entity/master-command.entity.ts +0 -13
- package/templates/src/master/entity/master-data-list.entity.ts +0 -13
- package/templates/src/master/entity/master-data.entity.ts +0 -13
- package/templates/src/master/master.module.ts +0 -19
package/README.md
CHANGED
|
@@ -4,11 +4,11 @@
|
|
|
4
4
|
|
|
5
5
|
## Description
|
|
6
6
|
|
|
7
|
-
The MBC CLI is a command-line interface tool that helps you
|
|
7
|
+
The MBC CLI is a command-line interface tool that helps you initialize and manage MBC CQRS Serverless applications. It provides commands for project creation, version management, and development workflow automation.
|
|
8
8
|
|
|
9
9
|
## Installation
|
|
10
10
|
|
|
11
|
-
To install `mbc` command, run:
|
|
11
|
+
To install the `mbc` command globally, run:
|
|
12
12
|
|
|
13
13
|
```bash
|
|
14
14
|
npm install -g @mbc-cqrs-serverless/cli
|
|
@@ -16,86 +16,117 @@ npm install -g @mbc-cqrs-serverless/cli
|
|
|
16
16
|
|
|
17
17
|
## Usage
|
|
18
18
|
|
|
19
|
-
###
|
|
19
|
+
### Project Creation
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
The CLI provides flexible options for creating new projects:
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
- Creates a new project in the `projectName` folder using the latest framework version.
|
|
27
|
-
- `mbc new [projectName@version]`
|
|
28
|
-
- If the specified version exists, the CLI uses that exact version.
|
|
29
|
-
- If the provided version is a prefix, the CLI uses the latest version matching that prefix.
|
|
30
|
-
- If no matching version is found, the CLI logs an error and provides a list of available versions for the user.
|
|
23
|
+
```bash
|
|
24
|
+
mbc new [projectName[@version]]
|
|
25
|
+
```
|
|
31
26
|
|
|
32
|
-
|
|
27
|
+
#### Basic Usage Examples
|
|
28
|
+
|
|
29
|
+
1. Create a new project in the current directory:
|
|
30
|
+
```bash
|
|
31
|
+
mbc new
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
2. Create a project with a specific name:
|
|
35
|
+
```bash
|
|
36
|
+
mbc new my-cqrs-app
|
|
37
|
+
```
|
|
33
38
|
|
|
39
|
+
3. Create a project with a specific version:
|
|
34
40
|
```bash
|
|
35
|
-
|
|
41
|
+
mbc new my-cqrs-app@0.1.45
|
|
36
42
|
```
|
|
37
43
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
3. Open in other terminal session and run npm run migrate to migrate RDS and dynamoDB table
|
|
42
|
-
4. Finally, run npm run offline:sls to start serverless offline mode.
|
|
44
|
+
### Project Structure
|
|
45
|
+
|
|
46
|
+
The CLI creates a standardized project structure:
|
|
43
47
|
|
|
44
|
-
|
|
48
|
+
```
|
|
49
|
+
my-cqrs-app/
|
|
50
|
+
├── src/
|
|
51
|
+
│ ├── commands/ # Command handlers
|
|
52
|
+
│ ├── events/ # Event handlers
|
|
53
|
+
│ ├── interfaces/ # TypeScript interfaces
|
|
54
|
+
│ └── services/ # Business logic services
|
|
55
|
+
├── test/
|
|
56
|
+
│ ├── e2e/ # End-to-end tests
|
|
57
|
+
│ └── unit/ # Unit tests
|
|
58
|
+
├── package.json
|
|
59
|
+
└── serverless.yml # Serverless Framework configuration
|
|
60
|
+
```
|
|
45
61
|
|
|
62
|
+
### Development Workflow
|
|
63
|
+
|
|
64
|
+
1. After creating a project, install dependencies:
|
|
46
65
|
```bash
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
serverless-offline-aws-eventbridge :: Plugin ready
|
|
50
|
-
serverless-offline-aws-eventbridge :: Mock server running at port: 4010
|
|
51
|
-
Starting Offline SQS at stage dev (ap-northeast-1)
|
|
52
|
-
Starting Offline Dynamodb Streams at stage dev (ap-northeast-1)
|
|
53
|
-
|
|
54
|
-
Starting Offline at stage dev (ap-northeast-1)
|
|
55
|
-
|
|
56
|
-
Offline [http for lambda] listening on http://localhost:3002
|
|
57
|
-
Function names exposed for local invocation by aws-sdk:
|
|
58
|
-
* main: serverless-example-dev-main
|
|
59
|
-
Configuring JWT Authorization: ANY /{proxy+}
|
|
60
|
-
|
|
61
|
-
┌────────────────────────────────────────────────────────────────────────┐
|
|
62
|
-
│ │
|
|
63
|
-
│ ANY | http://localhost:3000/api/public │
|
|
64
|
-
│ POST | http://localhost:3000/2015-03-31/functions/main/invocations │
|
|
65
|
-
│ ANY | http://localhost:3000/swagger-ui/{proxy*} │
|
|
66
|
-
│ POST | http://localhost:3000/2015-03-31/functions/main/invocations │
|
|
67
|
-
│ ANY | http://localhost:3000/{proxy*} │
|
|
68
|
-
│ POST | http://localhost:3000/2015-03-31/functions/main/invocations │
|
|
69
|
-
│ │
|
|
70
|
-
└────────────────────────────────────────────────────────────────────────┘
|
|
71
|
-
|
|
72
|
-
Server ready: http://localhost:3000 🚀
|
|
66
|
+
cd my-cqrs-app
|
|
67
|
+
npm install
|
|
73
68
|
```
|
|
74
69
|
|
|
75
|
-
|
|
70
|
+
2. Build the project:
|
|
71
|
+
```bash
|
|
72
|
+
npm run build
|
|
73
|
+
```
|
|
76
74
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
- SNS: http://localhost:4002
|
|
84
|
-
- SQS: http://localhost:9324
|
|
85
|
-
- SQS admin: http://localhost:9325
|
|
86
|
-
- Localstack: http://localhost:4566
|
|
87
|
-
- AppSync: http://localhost:4001
|
|
88
|
-
- Cognito: http://localhost:9229
|
|
89
|
-
- EventBridge: http://localhost:4010
|
|
90
|
-
- Simple Email Service: http://localhost:8005
|
|
91
|
-
- Run `npx prisma studio` to open studio web: http://localhost:5000
|
|
75
|
+
3. Start local development environment:
|
|
76
|
+
```bash
|
|
77
|
+
npm run offline:docker # Start local infrastructure
|
|
78
|
+
npm run migrate # Run database migrations
|
|
79
|
+
npm run offline:sls # Start serverless offline
|
|
80
|
+
```
|
|
92
81
|
|
|
82
|
+
### Available Commands
|
|
93
83
|
|
|
84
|
+
- `mbc new`: Create a new project
|
|
85
|
+
- `mbc version`: Display CLI version
|
|
86
|
+
- `mbc help`: Show command help
|
|
87
|
+
- `mbc list`: List available project templates
|
|
94
88
|
|
|
89
|
+
### Configuration
|
|
90
|
+
|
|
91
|
+
The CLI supports configuration through:
|
|
92
|
+
- Command line arguments
|
|
93
|
+
- Environment variables
|
|
94
|
+
- Configuration files
|
|
95
|
+
|
|
96
|
+
Example configuration file (`.mbcrc.json`):
|
|
97
|
+
```json
|
|
98
|
+
{
|
|
99
|
+
"defaultTemplate": "basic",
|
|
100
|
+
"region": "ap-northeast-1",
|
|
101
|
+
"stage": "dev"
|
|
102
|
+
}
|
|
103
|
+
```
|
|
95
104
|
|
|
96
105
|
## Documentation
|
|
97
106
|
|
|
98
|
-
Visit https://mbc-cqrs-serverless.mbc-net.com/ to view the full documentation
|
|
107
|
+
Visit https://mbc-cqrs-serverless.mbc-net.com/ to view the full documentation, including:
|
|
108
|
+
- Detailed CLI commands and options
|
|
109
|
+
- Project setup and configuration
|
|
110
|
+
- Development server setup
|
|
111
|
+
- Available endpoints and services
|
|
112
|
+
|
|
113
|
+
## Troubleshooting
|
|
114
|
+
|
|
115
|
+
Common issues and solutions:
|
|
116
|
+
|
|
117
|
+
1. Version not found:
|
|
118
|
+
```bash
|
|
119
|
+
mbc new myapp@999.999.999
|
|
120
|
+
# Error: Version not found. Available versions: [0.1.45, 0.1.44, ...]
|
|
121
|
+
```
|
|
122
|
+
Solution: Use `mbc list versions` to see available versions.
|
|
123
|
+
|
|
124
|
+
2. Project creation fails:
|
|
125
|
+
```bash
|
|
126
|
+
mbc new my-project
|
|
127
|
+
# Error: Directory not empty
|
|
128
|
+
```
|
|
129
|
+
Solution: Use a new directory or remove existing files.
|
|
99
130
|
|
|
100
131
|
## License
|
|
101
132
|
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.default = generateAction;
|
|
4
|
+
const schematic_runner_1 = require("../runners/schematic.runner");
|
|
5
|
+
const schematics_1 = require("../schematics");
|
|
6
|
+
const ui_1 = require("../ui");
|
|
7
|
+
/* eslint-disable no-console */
|
|
8
|
+
async function generateAction(schematic, name, options, command) {
|
|
9
|
+
ui_1.logger.info(`Executing command '${command.name()}' for application with options '${JSON.stringify(options)}'`);
|
|
10
|
+
const commandOptions = command.opts();
|
|
11
|
+
const formatOptions = [];
|
|
12
|
+
formatOptions.push({ name: 'dry-run', value: !!commandOptions.dryRun });
|
|
13
|
+
formatOptions.push({ name: 'mode', value: commandOptions.mode });
|
|
14
|
+
formatOptions.push({
|
|
15
|
+
name: 'schema',
|
|
16
|
+
value: !!commandOptions.schema || !!commandOptions.noSchema, // noSchema > schema
|
|
17
|
+
});
|
|
18
|
+
const inputs = [];
|
|
19
|
+
inputs.push({ name: 'schematic', value: schematic });
|
|
20
|
+
inputs.push({ name: 'name', value: name });
|
|
21
|
+
const fullInputs = formatOptions.concat(inputs);
|
|
22
|
+
const schematicOptions = mapSchematicOptions(fullInputs);
|
|
23
|
+
const runner = new schematic_runner_1.SchematicRunner();
|
|
24
|
+
const fullCommand = buildCommandLine(schematic, schematicOptions);
|
|
25
|
+
runner.run(fullCommand);
|
|
26
|
+
}
|
|
27
|
+
function buildCommandLine(name, options) {
|
|
28
|
+
return `@mbc-cqrs-serverless/cli:${name}${buildOptions(options)}`;
|
|
29
|
+
}
|
|
30
|
+
function buildOptions(options) {
|
|
31
|
+
return options.reduce((line, option) => {
|
|
32
|
+
return line.concat(` ${option.toCommandString()}`);
|
|
33
|
+
}, '');
|
|
34
|
+
}
|
|
35
|
+
const mapSchematicOptions = (inputs) => {
|
|
36
|
+
const excludedInputNames = ['schematic', 'spec', 'flat', 'specFileSuffix'];
|
|
37
|
+
const options = [];
|
|
38
|
+
inputs.forEach((input) => {
|
|
39
|
+
if (!excludedInputNames.includes(input.name) && input.value !== undefined) {
|
|
40
|
+
options.push(new schematics_1.SchematicOption(input.name, input.value));
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
return options;
|
|
44
|
+
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const child_process_1 = require("child_process");
|
|
4
|
+
const new_action_1 = require("./new.action");
|
|
5
|
+
const { getPackageVersion } = new_action_1.exportsForTesting;
|
|
6
|
+
jest.mock('child_process', () => ({
|
|
7
|
+
execSync: jest.fn(),
|
|
8
|
+
}));
|
|
9
|
+
describe('getPackageVersion', () => {
|
|
10
|
+
const mockExecSync = child_process_1.execSync;
|
|
11
|
+
const packageName = '@mbc-cqrs-serverless/core';
|
|
12
|
+
afterEach(() => {
|
|
13
|
+
jest.clearAllMocks();
|
|
14
|
+
});
|
|
15
|
+
it('should return the latest version when isLatest is true', () => {
|
|
16
|
+
const mockLatestVersion = '1.2.3';
|
|
17
|
+
mockExecSync.mockReturnValue(Buffer.from(`${mockLatestVersion}\n`));
|
|
18
|
+
const result = getPackageVersion(packageName, true);
|
|
19
|
+
expect(mockExecSync).toHaveBeenCalledWith(`npm view ${packageName} dist-tags.latest`);
|
|
20
|
+
expect(result).toEqual([mockLatestVersion]);
|
|
21
|
+
});
|
|
22
|
+
it('should return all versions when isLatest is false', () => {
|
|
23
|
+
const mockVersions = ['1.0.0', '1.1.0', '1.2.0'];
|
|
24
|
+
mockExecSync.mockReturnValue(Buffer.from(JSON.stringify(mockVersions)));
|
|
25
|
+
const result = getPackageVersion(packageName, false);
|
|
26
|
+
expect(mockExecSync).toHaveBeenCalledWith(`npm view ${packageName} versions --json`);
|
|
27
|
+
expect(result).toEqual(mockVersions);
|
|
28
|
+
});
|
|
29
|
+
});
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const child_process_1 = require("child_process");
|
|
4
|
+
const new_action_1 = require("./new.action");
|
|
5
|
+
const { isLatestCli } = new_action_1.exportsForTesting;
|
|
6
|
+
jest.mock('child_process', () => ({
|
|
7
|
+
execSync: jest.fn(),
|
|
8
|
+
}));
|
|
9
|
+
jest.mock('fs', () => ({
|
|
10
|
+
readFileSync: jest.fn(() => JSON.stringify({ version: '1.0.0' })),
|
|
11
|
+
}));
|
|
12
|
+
jest.mock('path', () => ({
|
|
13
|
+
join: jest.fn(() => '/mocked/path/to/package.json'),
|
|
14
|
+
}));
|
|
15
|
+
describe('isLatestCli', () => {
|
|
16
|
+
const mockExecSync = child_process_1.execSync;
|
|
17
|
+
afterEach(() => {
|
|
18
|
+
jest.clearAllMocks();
|
|
19
|
+
});
|
|
20
|
+
it('should return true if the current version matches the latest version', () => {
|
|
21
|
+
const mockLatestVersion = ['1.0.0'];
|
|
22
|
+
mockExecSync.mockReturnValue(Buffer.from(`${mockLatestVersion}\n`));
|
|
23
|
+
// Run the function
|
|
24
|
+
const result = isLatestCli();
|
|
25
|
+
// Assert that the result is true
|
|
26
|
+
expect(result).toBe(true);
|
|
27
|
+
});
|
|
28
|
+
it('should return false if the current version does not match the latest version', () => {
|
|
29
|
+
const mockLatestVersion = ['1.2.3'];
|
|
30
|
+
mockExecSync.mockReturnValue(Buffer.from(`${mockLatestVersion}\n`));
|
|
31
|
+
// Run the function
|
|
32
|
+
const result = isLatestCli();
|
|
33
|
+
// Assert that the result is true
|
|
34
|
+
expect(result).toBe(false);
|
|
35
|
+
});
|
|
36
|
+
});
|
|
@@ -5,13 +5,15 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.exportsForTesting = void 0;
|
|
7
7
|
exports.default = newAction;
|
|
8
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
8
9
|
const child_process_1 = require("child_process");
|
|
9
10
|
const fs_1 = require("fs");
|
|
10
11
|
const path_1 = __importDefault(require("path"));
|
|
12
|
+
const ui_1 = require("../ui");
|
|
11
13
|
/* eslint-disable no-console */
|
|
12
14
|
async function newAction(name = '', options, command) {
|
|
13
15
|
const [projectName, version = 'latest'] = name.split('@');
|
|
14
|
-
|
|
16
|
+
ui_1.logger.info(`Executing command '${command.name()}' for application '${projectName}' with options '${JSON.stringify(options)}'`);
|
|
15
17
|
let packageVersion;
|
|
16
18
|
if (version === 'latest') {
|
|
17
19
|
packageVersion = `^${getPackageVersion('@mbc-cqrs-serverless/core', true)[0]}`; // use the latest patch and minor versions
|
|
@@ -27,12 +29,12 @@ async function newAction(name = '', options, command) {
|
|
|
27
29
|
packageVersion = `^${matchVersions.at(-1)}`; // use the patch and minor versions
|
|
28
30
|
}
|
|
29
31
|
else {
|
|
30
|
-
|
|
32
|
+
ui_1.logger.error(`The specified package version does not exist. Please chose a valid version! ${versions}`);
|
|
31
33
|
return;
|
|
32
34
|
}
|
|
33
35
|
}
|
|
34
36
|
const destDir = path_1.default.join(process.cwd(), projectName);
|
|
35
|
-
|
|
37
|
+
ui_1.logger.title('MBC', `Generating MBC cqrs serverless application in ${chalk_1.default.green(destDir)}`);
|
|
36
38
|
(0, fs_1.mkdirSync)(destDir, { recursive: true });
|
|
37
39
|
useTemplate(destDir);
|
|
38
40
|
usePackageVersion(destDir, packageVersion, projectName);
|
|
@@ -49,12 +51,16 @@ async function newAction(name = '', options, command) {
|
|
|
49
51
|
// cp .env.local .env
|
|
50
52
|
(0, fs_1.copyFileSync)(path_1.default.join(destDir, '.env.local'), path_1.default.join(destDir, '.env'));
|
|
51
53
|
// git init
|
|
54
|
+
ui_1.logger.title('git', 'Initializing git repository.');
|
|
52
55
|
let logs = (0, child_process_1.execSync)('git init', { cwd: destDir });
|
|
53
|
-
|
|
56
|
+
ui_1.logger.success('Initialized a git repository.');
|
|
54
57
|
// npm install
|
|
55
|
-
|
|
56
|
-
logs = (0, child_process_1.execSync)('npm i', { cwd: destDir });
|
|
58
|
+
ui_1.logger.title('deps', `Installing dependencies`);
|
|
59
|
+
logs = (0, child_process_1.execSync)('npm i --ignore-scripts', { cwd: destDir });
|
|
60
|
+
(0, child_process_1.execSync)('npx prisma generate', { cwd: destDir });
|
|
57
61
|
console.log(logs.toString());
|
|
62
|
+
ui_1.logger.success(`Dependencies installed`);
|
|
63
|
+
ui_1.logger.title('MBC', `Your application was created!`);
|
|
58
64
|
}
|
|
59
65
|
function useTemplate(destDir) {
|
|
60
66
|
if (isLatestCli()) {
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const child_process_1 = require("child_process");
|
|
7
|
+
const commander_1 = require("commander");
|
|
8
|
+
const fs_1 = require("fs");
|
|
9
|
+
const path_1 = __importDefault(require("path"));
|
|
10
|
+
const new_action_1 = __importDefault(require("./new.action"));
|
|
11
|
+
jest.mock('child_process', () => ({
|
|
12
|
+
execSync: jest.fn(),
|
|
13
|
+
}));
|
|
14
|
+
jest.mock('fs', () => ({
|
|
15
|
+
copyFileSync: jest.fn(),
|
|
16
|
+
cpSync: jest.fn(),
|
|
17
|
+
mkdirSync: jest.fn(),
|
|
18
|
+
unlinkSync: jest.fn(),
|
|
19
|
+
writeFileSync: jest.fn(),
|
|
20
|
+
readFileSync: jest.fn(() => JSON.stringify({ version: '1.2.3', dependencies: {}, devDependencies: {} })),
|
|
21
|
+
}));
|
|
22
|
+
describe('newAction', () => {
|
|
23
|
+
const mockExecSync = child_process_1.execSync;
|
|
24
|
+
const mockCommand = new commander_1.Command().name('new'); // Mock command with name 'new'
|
|
25
|
+
beforeEach(() => {
|
|
26
|
+
jest.clearAllMocks();
|
|
27
|
+
});
|
|
28
|
+
it('should generate a project with the latest version when version is not specified', async () => {
|
|
29
|
+
const projectName = 'test-project';
|
|
30
|
+
const latestVersion = '1.2.3';
|
|
31
|
+
mockExecSync
|
|
32
|
+
.mockReturnValueOnce(Buffer.from(latestVersion)) // latest core
|
|
33
|
+
.mockReturnValueOnce(Buffer.from(latestVersion)) // latest cli
|
|
34
|
+
.mockReturnValue(Buffer.from(''));
|
|
35
|
+
await (0, new_action_1.default)(`${projectName}`, {}, mockCommand);
|
|
36
|
+
expect(child_process_1.execSync).toHaveBeenCalledWith('npm view @mbc-cqrs-serverless/core dist-tags.latest');
|
|
37
|
+
expect(fs_1.mkdirSync).toHaveBeenCalledWith(path_1.default.join(process.cwd(), projectName), { recursive: true });
|
|
38
|
+
expect(fs_1.cpSync).toHaveBeenCalledWith(path_1.default.join(__dirname, '../../templates'), path_1.default.join(process.cwd(), projectName), { recursive: true });
|
|
39
|
+
expect(fs_1.copyFileSync).toHaveBeenCalledTimes(3); // For .gitignore, infra/.gitignore and .env.local
|
|
40
|
+
expect(mockExecSync).toHaveBeenCalledWith('git init', {
|
|
41
|
+
cwd: path_1.default.join(process.cwd(), projectName),
|
|
42
|
+
});
|
|
43
|
+
expect(mockExecSync).toHaveBeenCalledWith('npm i --ignore-scripts', {
|
|
44
|
+
cwd: path_1.default.join(process.cwd(), projectName),
|
|
45
|
+
});
|
|
46
|
+
expect(mockExecSync).toHaveBeenCalledWith('npx prisma generate', {
|
|
47
|
+
cwd: path_1.default.join(process.cwd(), projectName),
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
it('should use a specific version if specified', async () => {
|
|
51
|
+
const projectName = 'test-project';
|
|
52
|
+
const version = '1.0.0';
|
|
53
|
+
const mockVersions = ['1.0.0', '1.1.0', '1.2.0'];
|
|
54
|
+
mockExecSync
|
|
55
|
+
.mockReturnValueOnce(Buffer.from(JSON.stringify(mockVersions))) // list version core
|
|
56
|
+
.mockReturnValueOnce(Buffer.from('1.2.3')) // latest cli
|
|
57
|
+
.mockReturnValue(Buffer.from(''));
|
|
58
|
+
await (0, new_action_1.default)(`${projectName}@${version}`, {}, mockCommand);
|
|
59
|
+
expect(child_process_1.execSync).toHaveBeenCalledWith('npm view @mbc-cqrs-serverless/core versions --json');
|
|
60
|
+
expect(fs_1.mkdirSync).toHaveBeenCalledWith(path_1.default.join(process.cwd(), projectName), { recursive: true });
|
|
61
|
+
expect(fs_1.cpSync).toHaveBeenCalledWith(path_1.default.join(__dirname, '../../templates'), path_1.default.join(process.cwd(), projectName), { recursive: true });
|
|
62
|
+
expect(fs_1.copyFileSync).toHaveBeenCalledTimes(3); // For .gitignore, infra/.gitignore and .env.local
|
|
63
|
+
expect(mockExecSync).toHaveBeenCalledWith('git init', {
|
|
64
|
+
cwd: path_1.default.join(process.cwd(), projectName),
|
|
65
|
+
});
|
|
66
|
+
expect(mockExecSync).toHaveBeenCalledWith('npm i --ignore-scripts', {
|
|
67
|
+
cwd: path_1.default.join(process.cwd(), projectName),
|
|
68
|
+
});
|
|
69
|
+
expect(mockExecSync).toHaveBeenCalledWith('npx prisma generate', {
|
|
70
|
+
cwd: path_1.default.join(process.cwd(), projectName),
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
it('should throw an error for an invalid version', async () => {
|
|
74
|
+
const projectName = 'test-project';
|
|
75
|
+
const invalidVersion = '2.0.0';
|
|
76
|
+
const mockVersions = ['1.0.0', '1.1.0', '1.2.0'];
|
|
77
|
+
mockExecSync.mockReturnValueOnce(Buffer.from(JSON.stringify(mockVersions)));
|
|
78
|
+
const consoleSpy = jest.spyOn(console, 'error').mockImplementation();
|
|
79
|
+
await (0, new_action_1.default)(`${projectName}@${invalidVersion}`, {}, mockCommand);
|
|
80
|
+
expect(child_process_1.execSync).toHaveBeenCalledWith('npm view @mbc-cqrs-serverless/core versions --json');
|
|
81
|
+
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining('The specified package version does not exist'));
|
|
82
|
+
consoleSpy.mockRestore();
|
|
83
|
+
});
|
|
84
|
+
});
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const fs_1 = require("fs");
|
|
4
|
+
const new_action_1 = require("./new.action");
|
|
5
|
+
const { updateEnvLocal } = new_action_1.exportsForTesting;
|
|
6
|
+
jest.mock('fs');
|
|
7
|
+
describe('updateEnvLocal', () => {
|
|
8
|
+
const mockEnvContent = `
|
|
9
|
+
# name of application
|
|
10
|
+
APP_NAME=%%projectName%%
|
|
11
|
+
# name of docker compose
|
|
12
|
+
COMPOSE_PROJECT_NAME=%%projectName%%
|
|
13
|
+
`;
|
|
14
|
+
const envPath = './.env.local';
|
|
15
|
+
beforeEach(() => {
|
|
16
|
+
jest.clearAllMocks();
|
|
17
|
+
});
|
|
18
|
+
it('should update the specified value in the .env.local file', () => {
|
|
19
|
+
const searchValue = '%%projectName%%';
|
|
20
|
+
const replaceValue = 'new-project-name';
|
|
21
|
+
fs_1.readFileSync.mockReturnValue(mockEnvContent);
|
|
22
|
+
updateEnvLocal(envPath, searchValue, replaceValue);
|
|
23
|
+
expect(fs_1.readFileSync).toHaveBeenCalledWith(envPath, 'utf8');
|
|
24
|
+
const expectedContent = mockEnvContent.replaceAll(searchValue, replaceValue);
|
|
25
|
+
expect(fs_1.writeFileSync).toHaveBeenCalledWith(envPath, expectedContent);
|
|
26
|
+
});
|
|
27
|
+
it('should not change the file content if searchValue is not found', () => {
|
|
28
|
+
const searchValue = 'non-existent-value';
|
|
29
|
+
const replaceValue = 'new-project-name';
|
|
30
|
+
fs_1.readFileSync.mockReturnValue(mockEnvContent);
|
|
31
|
+
updateEnvLocal(envPath, searchValue, replaceValue);
|
|
32
|
+
expect(fs_1.readFileSync).toHaveBeenCalledWith(envPath, 'utf8');
|
|
33
|
+
expect(fs_1.writeFileSync).toHaveBeenCalledWith(envPath, mockEnvContent);
|
|
34
|
+
});
|
|
35
|
+
});
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const faker_1 = require("@faker-js/faker");
|
|
7
|
+
const fs_1 = require("fs");
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const new_action_1 = require("./new.action");
|
|
10
|
+
const { usePackageVersion } = new_action_1.exportsForTesting;
|
|
11
|
+
// create testcase for usePackageVersion function in new.action.ts file
|
|
12
|
+
describe('usePackageVersion', () => {
|
|
13
|
+
const fname = path_1.default.join(__dirname, 'package.json');
|
|
14
|
+
const packageVersion = '1.0.0';
|
|
15
|
+
const packageJson = JSON.parse((0, fs_1.readFileSync)(path_1.default.join(__dirname, '../../package.json')).toString());
|
|
16
|
+
beforeEach(() => {
|
|
17
|
+
(0, fs_1.copyFileSync)(path_1.default.join(__dirname, '../../templates/package.json'), fname);
|
|
18
|
+
});
|
|
19
|
+
afterEach(() => {
|
|
20
|
+
(0, fs_1.unlinkSync)(fname);
|
|
21
|
+
});
|
|
22
|
+
it('it should update deps', () => {
|
|
23
|
+
usePackageVersion(__dirname, packageVersion);
|
|
24
|
+
const tplPackageJson = JSON.parse((0, fs_1.readFileSync)(fname).toString());
|
|
25
|
+
expect(tplPackageJson.dependencies['@mbc-cqrs-serverless/core']).toBe(packageVersion);
|
|
26
|
+
expect(packageJson.version).toBe(tplPackageJson.devDependencies['@mbc-cqrs-serverless/cli']);
|
|
27
|
+
});
|
|
28
|
+
it('it should not update name', () => {
|
|
29
|
+
const { name } = JSON.parse((0, fs_1.readFileSync)(fname).toString());
|
|
30
|
+
usePackageVersion(__dirname, packageVersion);
|
|
31
|
+
const tplPackageJson = JSON.parse((0, fs_1.readFileSync)(fname).toString());
|
|
32
|
+
expect(name).toBe(tplPackageJson.name);
|
|
33
|
+
});
|
|
34
|
+
it('it should not update name with empty name', () => {
|
|
35
|
+
const { name } = JSON.parse((0, fs_1.readFileSync)(fname).toString());
|
|
36
|
+
usePackageVersion(__dirname, packageVersion, '');
|
|
37
|
+
const tplPackageJson = JSON.parse((0, fs_1.readFileSync)(fname).toString());
|
|
38
|
+
expect(name).toBe(tplPackageJson.name);
|
|
39
|
+
});
|
|
40
|
+
it('it should update name', () => {
|
|
41
|
+
const name = faker_1.faker.word.sample();
|
|
42
|
+
usePackageVersion(__dirname, packageVersion, name);
|
|
43
|
+
const tplPackageJson = JSON.parse((0, fs_1.readFileSync)(fname).toString());
|
|
44
|
+
expect(name).toBe(tplPackageJson.name);
|
|
45
|
+
});
|
|
46
|
+
});
|
|
@@ -8,18 +8,19 @@ const child_process_1 = require("child_process");
|
|
|
8
8
|
const fs_1 = require("fs");
|
|
9
9
|
const path_1 = __importDefault(require("path"));
|
|
10
10
|
const rimraf_1 = require("rimraf");
|
|
11
|
+
const ui_1 = require("../ui");
|
|
11
12
|
const repoUrl = 'https://gitlab.com/mbc-net/common/mbc-cqrs-ui-common.git';
|
|
12
13
|
const componentOptions = ['all', 'appsync', 'component'];
|
|
13
14
|
/* eslint-disable no-console */
|
|
14
15
|
async function uiAction(options, command) {
|
|
15
|
-
|
|
16
|
+
ui_1.logger.info(`Executing command '${command.name()}' for application with options '${JSON.stringify(options)}'`);
|
|
16
17
|
const { branch, auth, component, pathDir, token = '' } = options;
|
|
17
18
|
if (componentOptions.findIndex((optionName) => optionName === component) === -1) {
|
|
18
|
-
|
|
19
|
+
ui_1.logger.error(`Please choose correct component options: ${componentOptions.join(', ')}`);
|
|
19
20
|
}
|
|
20
21
|
// Check command run in base src
|
|
21
22
|
if (!(0, fs_1.existsSync)(path_1.default.join(process.cwd(), 'tsconfig.json'))) {
|
|
22
|
-
|
|
23
|
+
ui_1.logger.error('Please run command in base folder');
|
|
23
24
|
return;
|
|
24
25
|
}
|
|
25
26
|
// Check tsconfig.json contain path @ms
|
|
@@ -27,7 +28,7 @@ async function uiAction(options, command) {
|
|
|
27
28
|
if (tsconfig?.compilerOptions &&
|
|
28
29
|
tsconfig?.compilerOptions?.paths &&
|
|
29
30
|
tsconfig?.compilerOptions?.paths.hasOwnProperty('@ms/*')) {
|
|
30
|
-
|
|
31
|
+
ui_1.logger.error('The project already contain mbc-cqrs-ui-common');
|
|
31
32
|
return;
|
|
32
33
|
}
|
|
33
34
|
// Copy source
|
|
@@ -52,9 +53,10 @@ async function uiAction(options, command) {
|
|
|
52
53
|
// Modify package.json
|
|
53
54
|
modifyDependencies({ pathDir, component });
|
|
54
55
|
// npm install
|
|
55
|
-
|
|
56
|
+
ui_1.logger.title('deps', `Installing dependencies`);
|
|
56
57
|
const logs = (0, child_process_1.execSync)('npm i');
|
|
57
58
|
console.log(logs.toString());
|
|
59
|
+
ui_1.logger.success(`Dependencies installed`);
|
|
58
60
|
}
|
|
59
61
|
const installTemplate = ({ auth, token, pathDir, branch, component, }) => {
|
|
60
62
|
let gitUrl = repoUrl;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.generateCommand = generateCommand;
|
|
7
|
+
const generate_action_1 = __importDefault(require("../actions/generate.action"));
|
|
8
|
+
const schematic_colection_1 = require("../schematics/schematic.colection");
|
|
9
|
+
async function generateCommand(program) {
|
|
10
|
+
program
|
|
11
|
+
.command('generate <schematic> [name]')
|
|
12
|
+
.alias('g')
|
|
13
|
+
.description(buildDescription())
|
|
14
|
+
.option('-d, --dry-run', 'Report actions that would be taken without writing out results.')
|
|
15
|
+
.option('--mode <mode>', 'Specify the mode of operation: sync or async (default: async)', 'async')
|
|
16
|
+
.option('--schema', 'Enable schema generation (default: true)', true)
|
|
17
|
+
.option('--no-schema', 'Disable schema generation (default: false)', false)
|
|
18
|
+
.action(generate_action_1.default);
|
|
19
|
+
}
|
|
20
|
+
function buildDescription() {
|
|
21
|
+
return ('Generate a MBC-cqrs-serverless element.\n' +
|
|
22
|
+
` Schematics available on the collection:\n` +
|
|
23
|
+
(0, schematic_colection_1.buildSchematicsListAsTable)());
|
|
24
|
+
}
|
package/dist/commands/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.default = loadCommands;
|
|
4
|
+
const generate_command_1 = require("./generate.command");
|
|
4
5
|
const new_command_1 = require("./new.command");
|
|
5
6
|
const start_command_1 = require("./start.command");
|
|
6
7
|
const ui_command_1 = require("./ui.command");
|
|
@@ -8,6 +9,7 @@ function loadCommands(program) {
|
|
|
8
9
|
(0, new_command_1.newCommand)(program);
|
|
9
10
|
(0, start_command_1.startCommand)(program);
|
|
10
11
|
(0, ui_command_1.uiCommand)(program);
|
|
12
|
+
(0, generate_command_1.generateCommand)(program);
|
|
11
13
|
// error handling
|
|
12
14
|
program.on('command:*', () => {
|
|
13
15
|
console.error(`\nInvalid command: '${program.args.join(' ')}'`);
|
package/dist/index.js
CHANGED
|
@@ -6,11 +6,22 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
7
|
const commander_1 = require("commander");
|
|
8
8
|
const commands_1 = __importDefault(require("./commands"));
|
|
9
|
+
const utils_1 = require("./utils");
|
|
9
10
|
async function bootstrap() {
|
|
10
11
|
const program = new commander_1.Command();
|
|
12
|
+
program
|
|
13
|
+
.version(
|
|
11
14
|
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
12
|
-
|
|
13
|
-
|
|
15
|
+
require('../package.json').version, '-v, --version', 'Output the current version.')
|
|
16
|
+
.usage('<command> [options]')
|
|
17
|
+
.helpOption('-h, --help', 'Output usage information.');
|
|
18
|
+
if ((0, utils_1.localBinExists)()) {
|
|
19
|
+
const localCommandLoader = (0, utils_1.loadLocalBinCommandLoader)();
|
|
20
|
+
localCommandLoader.default(program);
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
(0, commands_1.default)(program);
|
|
24
|
+
}
|
|
14
25
|
await program.parseAsync(process.argv);
|
|
15
26
|
if (!process.argv.slice(2).length) {
|
|
16
27
|
program.outputHelp();
|