@mbc-cqrs-serverless/cli 1.0.15 → 1.0.17

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 CHANGED
@@ -1,134 +1,295 @@
1
1
  ![MBC CQRS serverless framework](https://mbc-cqrs-serverless.mbc-net.com/img/mbc-cqrs-serverless.png)
2
2
 
3
- # MBC CQRS serverless framework CLI package
3
+ # @mbc-cqrs-serverless/cli
4
4
 
5
- ## Description
5
+ [![npm version](https://badge.fury.io/js/@mbc-cqrs-serverless%2Fcli.svg)](https://www.npmjs.com/package/@mbc-cqrs-serverless/cli)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
6
7
 
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
+ A command-line interface for the MBC CQRS Serverless framework. Quickly scaffold new projects, generate code, and manage your serverless CQRS applications.
9
+
10
+ ## Features
11
+
12
+ - **Project Scaffolding**: Create production-ready CQRS applications with a single command
13
+ - **Code Generation**: Generate modules, controllers, services, entities, and DTOs
14
+ - **Version Management**: Install specific framework versions or use the latest
15
+ - **Local Development**: Built-in commands for starting local development servers
8
16
 
9
17
  ## Installation
10
18
 
11
- To install the `mbc` command globally, run:
19
+ ### Global Installation (Recommended)
12
20
 
13
21
  ```bash
14
22
  npm install -g @mbc-cqrs-serverless/cli
15
23
  ```
16
24
 
17
- ## Usage
25
+ ### Version-Specific Installation
18
26
 
19
- ### Project Creation
27
+ ```bash
28
+ # Latest stable release
29
+ npm install -g @mbc-cqrs-serverless/cli
20
30
 
21
- The CLI provides flexible options for creating new projects:
31
+ # Beta release
32
+ npm install -g @mbc-cqrs-serverless/cli@beta
33
+
34
+ # Specific version
35
+ npm install -g @mbc-cqrs-serverless/cli@1.0.16
36
+ ```
37
+
38
+ Verify installation:
22
39
 
23
40
  ```bash
24
- mbc new [projectName[@version]]
41
+ mbc --version
25
42
  ```
26
43
 
27
- #### Basic Usage Examples
44
+ ## Quick Start
45
+
46
+ Create and run a new CQRS application in minutes:
28
47
 
29
- 1. Create a new project in the current directory:
30
48
  ```bash
49
+ # Create a new project
50
+ mbc new my-cqrs-app
51
+
52
+ # Navigate to project
53
+ cd my-cqrs-app
54
+
55
+ # Install dependencies
56
+ npm install
57
+
58
+ # Start local development (run in separate terminals)
59
+ npm run offline:docker # Terminal 1: Start Docker services
60
+ npm run migrate # Terminal 2: Run database migrations
61
+ npm run offline:sls # Terminal 3: Start serverless offline
62
+ ```
63
+
64
+ ## Commands
65
+
66
+ ### `mbc new [name[@version]]`
67
+
68
+ Generate a new CQRS application.
69
+
70
+ **Alias**: `n`
71
+
72
+ **Examples**:
73
+
74
+ ```bash
75
+ # Create project in current directory (prompts for name)
31
76
  mbc new
77
+
78
+ # Create project with a specific name
79
+ mbc new my-app
80
+
81
+ # Create project with a specific framework version
82
+ mbc new my-app@1.0.16
83
+
84
+ # Use alias
85
+ mbc n my-app
32
86
  ```
33
87
 
34
- 2. Create a project with a specific name:
88
+ ### `mbc generate <schematic> [name]`
89
+
90
+ Generate code elements using schematics.
91
+
92
+ **Alias**: `g`
93
+
94
+ **Options**:
95
+ - `-d, --dry-run` - Report actions without writing files
96
+ - `--mode <mode>` - Operation mode: sync or async (default: async)
97
+ - `--schema` / `--no-schema` - Enable/disable schema generation
98
+
99
+ **Available Schematics**:
100
+
101
+ | Name | Alias | Description |
102
+ |------|-------|-------------|
103
+ | `module` | `mo` | Create a module |
104
+ | `controller` | `co` | Create a controller |
105
+ | `service` | `se` | Create a service |
106
+ | `entity` | `en` | Create an entity |
107
+ | `dto` | `dto` | Create a DTO |
108
+
109
+ **Examples**:
110
+
35
111
  ```bash
36
- mbc new my-cqrs-app
112
+ # Generate a new module
113
+ mbc generate module todo
114
+
115
+ # Generate a controller (using alias)
116
+ mbc g co todo
117
+
118
+ # Generate a service with async mode
119
+ mbc g service todo --mode async
120
+
121
+ # Dry run to preview changes
122
+ mbc g module order --dry-run
37
123
  ```
38
124
 
39
- 3. Create a project with a specific version:
125
+ ### `mbc start`
126
+
127
+ Start the application with Serverless Framework.
128
+
129
+ **Alias**: `s`
130
+
131
+ ```bash
132
+ mbc start
133
+ # or
134
+ mbc s
135
+ ```
136
+
137
+ ### `mbc ui-common`
138
+
139
+ Add MBC CQRS UI common components to your project.
140
+
141
+ **Alias**: `ui`
142
+
143
+ **Options**:
144
+ - `-p, --pathDir <string>` - Path for common-ui (required)
145
+ - `-b, --branch <string>` - Branch name (default: main)
146
+ - `--auth <string>` - Auth method: HTTPS or SSH (default: SSH)
147
+ - `--token <string>` - Token for HTTPS auth (format: tokenId:tokenPassword)
148
+ - `-c, --component <string>` - Component to install: all, appsync, or component (default: all)
149
+ - `--alias` - Alias to common-ui
150
+
151
+ **Example**:
152
+
40
153
  ```bash
41
- mbc new my-cqrs-app@0.1.45
154
+ mbc ui-common -p ./src/common-ui -c all
42
155
  ```
43
156
 
44
- ### Project Structure
157
+ ## Project Structure
45
158
 
46
- The CLI creates a standardized project structure:
159
+ The CLI creates a standardized project structure optimized for CQRS:
47
160
 
48
161
  ```
49
162
  my-cqrs-app/
50
163
  ├── src/
51
- │ ├── commands/ # Command handlers
52
- │ ├── events/ # Event handlers
53
- │ ├── interfaces/ # TypeScript interfaces
54
- └── services/ # Business logic services
164
+ │ ├── app.module.ts # Root application module
165
+ │ ├── main.ts # Application entry point
166
+ │ ├── todo/ # Example module (optional)
167
+ │ ├── todo.module.ts # Module definition
168
+ │ │ ├── todo.controller.ts # REST controller
169
+ │ │ ├── todo.service.ts # Business logic
170
+ │ │ ├── dto/ # Data transfer objects
171
+ │ │ │ ├── create-todo.dto.ts
172
+ │ │ │ └── update-todo.dto.ts
173
+ │ │ └── entity/ # Entity definitions
174
+ │ │ └── todo.entity.ts
175
+ │ ├── prisma/ # Prisma ORM configuration
176
+ │ │ ├── schema.prisma # Database schema
177
+ │ │ └── prisma.service.ts # Prisma service
178
+ │ └── helpers/ # Utility functions
179
+ ├── infra-local/ # Local infrastructure config
180
+ │ └── cognito-local/ # Local Cognito setup
55
181
  ├── test/
56
- │ ├── e2e/ # End-to-end tests
57
- │ └── unit/ # Unit tests
58
- ├── package.json
59
- └── serverless.yml # Serverless Framework configuration
182
+ │ ├── e2e/ # End-to-end tests
183
+ │ └── unit/ # Unit tests
184
+ ├── .env.example # Environment template
185
+ ├── docker-compose.yml # Docker services
186
+ ├── package.json # Dependencies
187
+ ├── serverless.yml # Serverless Framework config
188
+ └── tsconfig.json # TypeScript configuration
60
189
  ```
61
190
 
62
- ### Development Workflow
191
+ ## Development Workflow
192
+
193
+ ### 1. Create Project
63
194
 
64
- 1. After creating a project, install dependencies:
65
195
  ```bash
196
+ mbc new my-cqrs-app
66
197
  cd my-cqrs-app
67
198
  npm install
68
199
  ```
69
200
 
70
- 2. Build the project:
201
+ ### 2. Configure Environment
202
+
71
203
  ```bash
72
- npm run build
204
+ cp .env.example .env
205
+ # Edit .env with your settings
73
206
  ```
74
207
 
75
- 3. Start local development environment:
208
+ ### 3. Start Local Infrastructure
209
+
76
210
  ```bash
77
- npm run offline:docker # Start local infrastructure
78
- npm run migrate # Run database migrations
79
- npm run offline:sls # Start serverless offline
211
+ # Start Docker services (DynamoDB Local, LocalStack, etc.)
212
+ npm run offline:docker
80
213
  ```
81
214
 
82
- ### Available Commands
215
+ ### 4. Initialize Database
83
216
 
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
217
+ ```bash
218
+ # Run Prisma migrations
219
+ npm run migrate
220
+ ```
88
221
 
89
- ### Configuration
222
+ ### 5. Start Development Server
90
223
 
91
- The CLI supports configuration through:
92
- - Command line arguments
93
- - Environment variables
94
- - Configuration files
224
+ ```bash
225
+ # Start Serverless Offline
226
+ npm run offline:sls
227
+ ```
228
+
229
+ ### 6. Generate New Components
95
230
 
96
- Example configuration file (`.mbcrc.json`):
97
- ```json
98
- {
99
- "defaultTemplate": "basic",
100
- "region": "ap-northeast-1",
101
- "stage": "dev"
102
- }
231
+ ```bash
232
+ # Add a new module
233
+ mbc g module order
234
+
235
+ # Add related components
236
+ mbc g controller order
237
+ mbc g service order
238
+ mbc g entity order
239
+ mbc g dto order
103
240
  ```
104
241
 
242
+ ## Related Packages
243
+
244
+ | Package | Description |
245
+ |---------|-------------|
246
+ | [@mbc-cqrs-serverless/core](https://www.npmjs.com/package/@mbc-cqrs-serverless/core) | Core CQRS framework |
247
+ | [@mbc-cqrs-serverless/sequence](https://www.npmjs.com/package/@mbc-cqrs-serverless/sequence) | Sequence number generation |
248
+ | [@mbc-cqrs-serverless/task](https://www.npmjs.com/package/@mbc-cqrs-serverless/task) | Async task processing |
249
+ | [@mbc-cqrs-serverless/master](https://www.npmjs.com/package/@mbc-cqrs-serverless/master) | Master data management |
250
+ | [@mbc-cqrs-serverless/tenant](https://www.npmjs.com/package/@mbc-cqrs-serverless/tenant) | Multi-tenancy support |
251
+ | [@mbc-cqrs-serverless/import](https://www.npmjs.com/package/@mbc-cqrs-serverless/import) | Data import utilities |
252
+ | [@mbc-cqrs-serverless/ui-setting](https://www.npmjs.com/package/@mbc-cqrs-serverless/ui-setting) | UI configuration |
253
+
105
254
  ## Documentation
106
255
 
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
256
+ Full documentation is available at [https://mbc-cqrs-serverless.mbc-net.com/](https://mbc-cqrs-serverless.mbc-net.com/)
257
+
258
+ - [Getting Started](https://mbc-cqrs-serverless.mbc-net.com/docs/introduction)
259
+ - [CLI Reference](https://mbc-cqrs-serverless.mbc-net.com/docs/cli)
260
+ - [Build a Todo App Tutorial](https://mbc-cqrs-serverless.mbc-net.com/docs/build-todo-app)
112
261
 
113
262
  ## Troubleshooting
114
263
 
115
- Common issues and solutions:
264
+ ### Version Not Found
116
265
 
117
- 1. Version not found:
118
266
  ```bash
119
267
  mbc new myapp@999.999.999
120
- # Error: Version not found. Available versions: [0.1.45, 0.1.44, ...]
268
+ # Error: Version not found
121
269
  ```
122
- Solution: Use `mbc list versions` to see available versions.
123
270
 
124
- 2. Project creation fails:
271
+ **Solution**: Check available versions on [npm](https://www.npmjs.com/package/@mbc-cqrs-serverless/cli?activeTab=versions).
272
+
273
+ ### Project Creation Fails
274
+
125
275
  ```bash
126
276
  mbc new my-project
127
277
  # Error: Directory not empty
128
278
  ```
129
- Solution: Use a new directory or remove existing files.
279
+
280
+ **Solution**: Use a new directory or remove existing files first.
281
+
282
+ ### Permission Denied
283
+
284
+ ```bash
285
+ npm install -g @mbc-cqrs-serverless/cli
286
+ # EACCES: permission denied
287
+ ```
288
+
289
+ **Solution**: Fix npm permissions or use a Node version manager like nvm.
130
290
 
131
291
  ## License
132
292
 
133
- Copyright &copy; 2024, Murakami Business Consulting, Inc. https://www.mbc-net.com/
134
- This project and sub projects are under the MIT License.
293
+ Copyright © 2024-2025, Murakami Business Consulting, Inc. [https://www.mbc-net.com/](https://www.mbc-net.com/)
294
+
295
+ This project is under the [MIT License](../../LICENSE.txt).
@@ -1,26 +1,104 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
2
35
  var __importDefault = (this && this.__importDefault) || function (mod) {
3
36
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
37
  };
5
38
  Object.defineProperty(exports, "__esModule", { value: true });
6
39
  const generate_action_1 = __importDefault(require("./generate.action"));
40
+ const fs = __importStar(require("fs"));
41
+ const path = __importStar(require("path"));
7
42
  describe('Generate Action', () => {
43
+ // Use dryRun: true by default to avoid creating actual files during tests
44
+ // テスト中に実際のファイルを作成しないように、デフォルトで dryRun: true を使用
8
45
  const mockCommand = {
9
46
  name: () => 'generate',
10
47
  opts: () => ({
11
- dryRun: false,
48
+ dryRun: true,
12
49
  mode: 'async',
13
50
  schema: true
14
51
  })
15
52
  };
16
53
  const mockOptions = {
17
- dryRun: false,
54
+ dryRun: true,
18
55
  mode: 'async',
19
56
  schema: true
20
57
  };
58
+ // Directories that may be created by tests
59
+ // テストで作成される可能性があるディレクトリ
60
+ const testDirs = ['src', 'test'];
21
61
  beforeEach(() => {
22
62
  jest.clearAllMocks();
23
63
  });
64
+ afterAll(() => {
65
+ // Clean up any directories created during tests
66
+ // テスト中に作成されたディレクトリを削除
67
+ // The monorepo root is determined by finding package.json with "workspaces"
68
+ let rootDir = process.cwd();
69
+ // Walk up to find monorepo root (has workspaces in package.json)
70
+ let current = rootDir;
71
+ for (let i = 0; i < 10; i++) {
72
+ const pkgPath = path.join(current, 'package.json');
73
+ if (fs.existsSync(pkgPath)) {
74
+ try {
75
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
76
+ if (pkg.workspaces) {
77
+ rootDir = current;
78
+ break;
79
+ }
80
+ }
81
+ catch {
82
+ // ignore
83
+ }
84
+ }
85
+ const parent = path.dirname(current);
86
+ if (parent === current)
87
+ break;
88
+ current = parent;
89
+ }
90
+ for (const dir of testDirs) {
91
+ const dirPath = path.join(rootDir, dir);
92
+ if (fs.existsSync(dirPath)) {
93
+ try {
94
+ fs.rmSync(dirPath, { recursive: true, force: true });
95
+ }
96
+ catch (error) {
97
+ console.warn(`Failed to clean up directory: ${dirPath}`);
98
+ }
99
+ }
100
+ }
101
+ });
24
102
  describe('Overview: Schematic generation functionality', () => {
25
103
  describe('Purpose: Test basic generate action execution', () => {
26
104
  it('should execute generate action without errors', async () => {
@@ -87,7 +165,7 @@ describe('Generate Action', () => {
87
165
  const asyncCommand = {
88
166
  ...mockCommand,
89
167
  opts: () => ({
90
- dryRun: false,
168
+ dryRun: true,
91
169
  mode: 'async',
92
170
  schema: true
93
171
  })
@@ -98,7 +176,7 @@ describe('Generate Action', () => {
98
176
  const syncCommand = {
99
177
  ...mockCommand,
100
178
  opts: () => ({
101
- dryRun: false,
179
+ dryRun: true,
102
180
  mode: 'sync',
103
181
  schema: false
104
182
  })
@@ -109,7 +187,7 @@ describe('Generate Action', () => {
109
187
  const noSchemaCommand = {
110
188
  ...mockCommand,
111
189
  opts: () => ({
112
- dryRun: false,
190
+ dryRun: true,
113
191
  mode: 'async',
114
192
  noSchema: true
115
193
  })
@@ -19,27 +19,21 @@ describe('Abstract Runner', () => {
19
19
  it('should execute command successfully with default options', async () => {
20
20
  const runner = new abstract_runner_1.AbstractRunner('npm', ['--version']);
21
21
  const runPromise = runner.run('install');
22
- setTimeout(() => {
23
- mockChildProcess.emit('close', 0);
24
- }, 10);
22
+ mockChildProcess.emit('close', 0);
25
23
  await expect(runPromise).resolves.toBeNull();
26
24
  expect(mockSpawn).toHaveBeenCalledWith('npm', ['--version', 'install'], expect.any(Object));
27
25
  });
28
26
  it('should execute command with custom arguments', async () => {
29
27
  const runner = new abstract_runner_1.AbstractRunner('node', ['-v']);
30
28
  const runPromise = runner.run('--help');
31
- setTimeout(() => {
32
- mockChildProcess.emit('close', 0);
33
- }, 10);
29
+ mockChildProcess.emit('close', 0);
34
30
  await expect(runPromise).resolves.toBeNull();
35
31
  expect(mockSpawn).toHaveBeenCalledWith('node', ['-v', '--help'], expect.any(Object));
36
32
  });
37
33
  it('should collect output when collectResult is true', async () => {
38
34
  const runner = new abstract_runner_1.AbstractRunner('echo', ['hello']);
39
35
  const runPromise = runner.run('world', true);
40
- setTimeout(() => {
41
- mockChildProcess.stdout.emit('data', Buffer.from('hello\n'));
42
- }, 10);
36
+ mockChildProcess.stdout.emit('data', Buffer.from('hello\n'));
43
37
  const result = await runPromise;
44
38
  expect(result).toBe('hello');
45
39
  });
@@ -48,25 +42,19 @@ describe('Abstract Runner', () => {
48
42
  it('should handle command execution failure', async () => {
49
43
  const runner = new abstract_runner_1.AbstractRunner('invalid-command', []);
50
44
  const runPromise = runner.run('test');
51
- setTimeout(() => {
52
- mockChildProcess.emit('close', 1);
53
- }, 10);
45
+ mockChildProcess.emit('close', 1);
54
46
  await expect(runPromise).rejects.toBeUndefined();
55
47
  });
56
48
  it('should handle spawn errors', async () => {
57
49
  const runner = new abstract_runner_1.AbstractRunner('invalid-command', []);
58
50
  const runPromise = runner.run('test');
59
- setTimeout(() => {
60
- mockChildProcess.emit('close', 1);
61
- }, 10);
51
+ mockChildProcess.emit('close', 1);
62
52
  await expect(runPromise).rejects.toBeUndefined();
63
53
  });
64
54
  it('should handle stderr output as error', async () => {
65
55
  const runner = new abstract_runner_1.AbstractRunner('test-command', []);
66
56
  const runPromise = runner.run('test');
67
- setTimeout(() => {
68
- mockChildProcess.emit('close', 1);
69
- }, 10);
57
+ mockChildProcess.emit('close', 1);
70
58
  await expect(runPromise).rejects.toBeUndefined();
71
59
  });
72
60
  });
@@ -91,27 +79,21 @@ describe('Abstract Runner', () => {
91
79
  it('should collect stdout when collectResult is enabled', async () => {
92
80
  const runner = new abstract_runner_1.AbstractRunner('cat', ['file.txt']);
93
81
  const runPromise = runner.run('test', true);
94
- setTimeout(() => {
95
- mockChildProcess.stdout.emit('data', Buffer.from('line 1\n'));
96
- }, 10);
82
+ mockChildProcess.stdout.emit('data', Buffer.from('line 1\n'));
97
83
  const result = await runPromise;
98
84
  expect(result).toBe('line 1');
99
85
  });
100
86
  it('should not collect output when collectResult is false', async () => {
101
87
  const runner = new abstract_runner_1.AbstractRunner('echo', ['test']);
102
88
  const runPromise = runner.run('command', false);
103
- setTimeout(() => {
104
- mockChildProcess.emit('close', 0);
105
- }, 10);
89
+ mockChildProcess.emit('close', 0);
106
90
  const result = await runPromise;
107
91
  expect(result).toBeNull();
108
92
  });
109
93
  it('should handle empty stdout output', async () => {
110
94
  const runner = new abstract_runner_1.AbstractRunner('true', []);
111
95
  const runPromise = runner.run('test', false);
112
- setTimeout(() => {
113
- mockChildProcess.emit('close', 0);
114
- }, 10);
96
+ mockChildProcess.emit('close', 0);
115
97
  const result = await runPromise;
116
98
  expect(result).toBeNull();
117
99
  });
@@ -120,17 +102,13 @@ describe('Abstract Runner', () => {
120
102
  it('should handle process exit with signal', async () => {
121
103
  const runner = new abstract_runner_1.AbstractRunner('test-command', []);
122
104
  const runPromise = runner.run('test');
123
- setTimeout(() => {
124
- mockChildProcess.emit('close', null, 'SIGTERM');
125
- }, 10);
105
+ mockChildProcess.emit('close', null, 'SIGTERM');
126
106
  await expect(runPromise).rejects.toBeUndefined();
127
107
  });
128
108
  it('should handle multiple stderr chunks', async () => {
129
109
  const runner = new abstract_runner_1.AbstractRunner('test-command', []);
130
110
  const runPromise = runner.run('test');
131
- setTimeout(() => {
132
- mockChildProcess.emit('close', 1);
133
- }, 10);
111
+ mockChildProcess.emit('close', 1);
134
112
  await expect(runPromise).rejects.toBeUndefined();
135
113
  });
136
114
  it('should handle very long command arguments', async () => {
@@ -147,21 +125,18 @@ describe('Abstract Runner', () => {
147
125
  const runner2 = new abstract_runner_1.AbstractRunner('echo', ['test2']);
148
126
  const promise1 = runner1.run('command1');
149
127
  const promise2 = runner2.run('command2');
150
- setTimeout(() => {
151
- mockChildProcess.emit('close', 0);
152
- }, 10);
128
+ mockChildProcess.emit('close', 0);
153
129
  const results = await Promise.all([promise1, promise2]);
154
130
  expect(results).toEqual([null, null]);
155
131
  });
156
132
  it('should handle rapid successive runs', async () => {
157
133
  const runner = new abstract_runner_1.AbstractRunner('echo', ['test']);
158
- const promises = Array(5).fill(null).map((_, i) => {
159
- const promise = runner.run(`command${i}`);
160
- setTimeout(() => {
161
- mockChildProcess.emit('close', 0);
162
- }, 10 + i);
163
- return promise;
134
+ const promises = Array(5)
135
+ .fill(null)
136
+ .map((_, i) => {
137
+ return runner.run(`command${i}`);
164
138
  });
139
+ mockChildProcess.emit('close', 0);
165
140
  const results = await Promise.all(promises);
166
141
  expect(results).toEqual([null, null, null, null, null]);
167
142
  });
@@ -146,7 +146,7 @@ export class <%= classify(name) %>Service {
146
146
 
147
147
  const data = (await this.dataService.getItem(key)) as <%= classify(name) %>DataEntity
148
148
  if (!data) {
149
- throw new NotFoundException()
149
+ throw new NotFoundException('<%= classify(name) %> not found')
150
150
  }
151
151
  const commandDto: CommandPartialInputModel = {
152
152
  pk: data.pk,
@@ -146,7 +146,7 @@ export class <%= classify(name) %>Service {
146
146
 
147
147
  const data = (await this.dataService.getItem(key)) as <%= classify(name) %>DataEntity
148
148
  if (!data) {
149
- throw new NotFoundException()
149
+ throw new NotFoundException('<%= classify(name) %> not found')
150
150
  }
151
151
  const commandDto: CommandPartialInputModel = {
152
152
  pk: data.pk,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mbc-cqrs-serverless/cli",
3
- "version": "1.0.15",
3
+ "version": "1.0.17",
4
4
  "description": "a CLI to get started with MBC CQRS serverless framework",
5
5
  "keywords": [
6
6
  "mbc",
@@ -58,5 +58,5 @@
58
58
  "@faker-js/faker": "^8.3.1",
59
59
  "copyfiles": "^2.4.1"
60
60
  },
61
- "gitHead": "69711a8dab16182f8ef59687ee5a7d6d3d99932b"
61
+ "gitHead": "1870821803cfb045c9c4d6bc18d513fa2558de1c"
62
62
  }
@@ -312,21 +312,6 @@
312
312
  "url": "https://github.com/sponsors/jonschlinkert"
313
313
  }
314
314
  },
315
- "node_modules/@angular-devkit/schematics-cli/node_modules/readdirp": {
316
- "version": "4.1.2",
317
- "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz",
318
- "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==",
319
- "dev": true,
320
- "license": "MIT",
321
- "optional": true,
322
- "engines": {
323
- "node": ">= 14.18.0"
324
- },
325
- "funding": {
326
- "type": "individual",
327
- "url": "https://paulmillr.com/funding/"
328
- }
329
- },
330
315
  "node_modules/@aws-crypto/crc32": {
331
316
  "version": "5.2.0",
332
317
  "resolved": "https://registry.npmjs.org/@aws-crypto/crc32/-/crc32-5.2.0.tgz",
@@ -689,7 +674,6 @@
689
674
  "resolved": "https://registry.npmjs.org/@aws-sdk/client-dynamodb/-/client-dynamodb-3.665.0.tgz",
690
675
  "integrity": "sha512-W1idOmV4bDzUxZhkYbDGzmNwJ5Lf61UIOGUUAva5A2CpfVm2qTGRhEnowj6PEv5I06O/gMTsJpJVJxypzKdLQQ==",
691
676
  "devOptional": true,
692
- "peer": true,
693
677
  "dependencies": {
694
678
  "@aws-crypto/sha256-browser": "5.2.0",
695
679
  "@aws-crypto/sha256-js": "5.2.0",
@@ -908,7 +892,6 @@
908
892
  "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.665.0.tgz",
909
893
  "integrity": "sha512-jlXlF/YiCZyieSmYSU5R0kViU+pKJSKlGHaz+L1uXlpuoMiyNsSC3CGRzvtijBdgMU/vacVcAuj/tC/iov4usg==",
910
894
  "devOptional": true,
911
- "peer": true,
912
895
  "dependencies": {
913
896
  "@aws-crypto/sha1-browser": "5.2.0",
914
897
  "@aws-crypto/sha256-browser": "5.2.0",
@@ -2355,7 +2338,6 @@
2355
2338
  "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.665.0.tgz",
2356
2339
  "integrity": "sha512-FQ2YyM9/6y3clWkf3d60/W4c/HZy61hbfIsR4KIh8aGOifwfIx/UpZQ61pCr/TXTNqbaAVU2/sK+J1zFkGEoLw==",
2357
2340
  "devOptional": true,
2358
- "peer": true,
2359
2341
  "dependencies": {
2360
2342
  "@aws-crypto/sha256-browser": "5.2.0",
2361
2343
  "@aws-crypto/sha256-js": "5.2.0",
@@ -2409,7 +2391,6 @@
2409
2391
  "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.665.0.tgz",
2410
2392
  "integrity": "sha512-/OQEaWB1euXhZ/hV+wetDw1tynlrkNKzirzoiFuJ1EQsiIb9Ih/qjUF9KLdF1+/bXbnGu5YvIaAx80YReUchjg==",
2411
2393
  "devOptional": true,
2412
- "peer": true,
2413
2394
  "dependencies": {
2414
2395
  "@aws-crypto/sha256-browser": "5.2.0",
2415
2396
  "@aws-crypto/sha256-js": "5.2.0",
@@ -4187,7 +4168,6 @@
4187
4168
  "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.25.7.tgz",
4188
4169
  "integrity": "sha512-yJ474Zv3cwiSOO9nXJuqzvwEeM+chDuQ8GJirw+pZ91sCGCyOZ3dJkVE09fTV0VEVzXyLWhh3G/AolYTPX7Mow==",
4189
4170
  "dev": true,
4190
- "peer": true,
4191
4171
  "dependencies": {
4192
4172
  "@ampproject/remapping": "^2.2.0",
4193
4173
  "@babel/code-frame": "^7.25.7",
@@ -6628,7 +6608,6 @@
6628
6608
  "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==",
6629
6609
  "dev": true,
6630
6610
  "license": "MIT",
6631
- "peer": true,
6632
6611
  "dependencies": {
6633
6612
  "readdirp": "^4.0.1"
6634
6613
  },
@@ -6796,7 +6775,6 @@
6796
6775
  "version": "10.4.4",
6797
6776
  "resolved": "https://registry.npmjs.org/@nestjs/common/-/common-10.4.4.tgz",
6798
6777
  "integrity": "sha512-0j2/zqRw9nvHV1GKTktER8B/hIC/Z8CYFjN/ZqUuvwayCH+jZZBhCR2oRyuvLTXdnlSmtCAg2xvQ0ULqQvzqhA==",
6799
- "peer": true,
6800
6778
  "dependencies": {
6801
6779
  "iterare": "1.2.1",
6802
6780
  "tslib": "2.7.0",
@@ -8298,7 +8276,6 @@
8298
8276
  "integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==",
8299
8277
  "dev": true,
8300
8278
  "license": "MIT",
8301
- "peer": true,
8302
8279
  "dependencies": {
8303
8280
  "@types/estree": "*",
8304
8281
  "@types/json-schema": "*"
@@ -8461,7 +8438,6 @@
8461
8438
  "resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.10.tgz",
8462
8439
  "integrity": "sha512-vQUKgWTjEIRFCvK6CyriPH3MZYiYlNy0fKiEYHWbcoWLEgs4opurGGKlebrTLqdSMIbXImH6XExNiIyNUv3WpA==",
8463
8440
  "dev": true,
8464
- "peer": true,
8465
8441
  "dependencies": {
8466
8442
  "undici-types": "~6.19.2"
8467
8443
  }
@@ -8625,7 +8601,6 @@
8625
8601
  "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.21.0.tgz",
8626
8602
  "integrity": "sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==",
8627
8603
  "dev": true,
8628
- "peer": true,
8629
8604
  "dependencies": {
8630
8605
  "@typescript-eslint/scope-manager": "6.21.0",
8631
8606
  "@typescript-eslint/types": "6.21.0",
@@ -9034,7 +9009,6 @@
9034
9009
  "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
9035
9010
  "dev": true,
9036
9011
  "license": "MIT",
9037
- "peer": true,
9038
9012
  "bin": {
9039
9013
  "acorn": "bin/acorn"
9040
9014
  },
@@ -9161,7 +9135,6 @@
9161
9135
  "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz",
9162
9136
  "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==",
9163
9137
  "dev": true,
9164
- "peer": true,
9165
9138
  "dependencies": {
9166
9139
  "fast-deep-equal": "^3.1.1",
9167
9140
  "json-schema-traverse": "^1.0.0",
@@ -10265,7 +10238,6 @@
10265
10238
  "url": "https://github.com/sponsors/ai"
10266
10239
  }
10267
10240
  ],
10268
- "peer": true,
10269
10241
  "dependencies": {
10270
10242
  "caniuse-lite": "^1.0.30001663",
10271
10243
  "electron-to-chromium": "^1.5.28",
@@ -10752,7 +10724,6 @@
10752
10724
  "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
10753
10725
  "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==",
10754
10726
  "dev": true,
10755
- "peer": true,
10756
10727
  "dependencies": {
10757
10728
  "anymatch": "~3.1.2",
10758
10729
  "braces": "~3.0.2",
@@ -12785,7 +12756,6 @@
12785
12756
  "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==",
12786
12757
  "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.",
12787
12758
  "dev": true,
12788
- "peer": true,
12789
12759
  "dependencies": {
12790
12760
  "@eslint-community/eslint-utils": "^4.2.0",
12791
12761
  "@eslint-community/regexpp": "^4.6.1",
@@ -12841,7 +12811,6 @@
12841
12811
  "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz",
12842
12812
  "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==",
12843
12813
  "dev": true,
12844
- "peer": true,
12845
12814
  "bin": {
12846
12815
  "eslint-config-prettier": "bin/cli.js"
12847
12816
  },
@@ -15943,7 +15912,6 @@
15943
15912
  "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz",
15944
15913
  "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==",
15945
15914
  "dev": true,
15946
- "peer": true,
15947
15915
  "dependencies": {
15948
15916
  "@jest/core": "^29.7.0",
15949
15917
  "@jest/types": "^29.6.3",
@@ -16737,7 +16705,6 @@
16737
16705
  "resolved": "https://registry.npmjs.org/jsep/-/jsep-1.3.9.tgz",
16738
16706
  "integrity": "sha512-i1rBX5N7VPl0eYb6+mHNp52sEuaS2Wi8CDYx1X5sn9naevL78+265XJqy1qENEk7mRKwS06NHpUqiBwR7qeodw==",
16739
16707
  "dev": true,
16740
- "peer": true,
16741
16708
  "engines": {
16742
16709
  "node": ">= 10.16.0"
16743
16710
  }
@@ -17520,7 +17487,6 @@
17520
17487
  "resolved": "https://registry.npmjs.org/log/-/log-6.3.2.tgz",
17521
17488
  "integrity": "sha512-ek8NRg/OPvS9ISOJNWNAz5vZcpYacWNFDWNJjj5OXsc6YuKacfey6wF04cXz/tOJIVrZ2nGSkHpAY5qKtF6ISg==",
17522
17489
  "dev": true,
17523
- "peer": true,
17524
17490
  "dependencies": {
17525
17491
  "d": "^1.0.2",
17526
17492
  "duration": "^0.2.2",
@@ -19360,7 +19326,6 @@
19360
19326
  "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz",
19361
19327
  "integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==",
19362
19328
  "dev": true,
19363
- "peer": true,
19364
19329
  "bin": {
19365
19330
  "prettier": "bin/prettier.cjs"
19366
19331
  },
@@ -19414,7 +19379,6 @@
19414
19379
  "resolved": "https://registry.npmjs.org/prisma/-/prisma-5.20.0.tgz",
19415
19380
  "integrity": "sha512-6obb3ucKgAnsGS9x9gLOe8qa51XxvJ3vLQtmyf52CTey1Qcez3A6W6ROH5HIz5Q5bW+0VpmZb8WBohieMFGpig==",
19416
19381
  "hasInstallScript": true,
19417
- "peer": true,
19418
19382
  "dependencies": {
19419
19383
  "@prisma/engines": "5.20.0"
19420
19384
  },
@@ -20014,7 +19978,6 @@
20014
19978
  "version": "7.8.1",
20015
19979
  "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz",
20016
19980
  "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==",
20017
- "peer": true,
20018
19981
  "dependencies": {
20019
19982
  "tslib": "^2.1.0"
20020
19983
  }
@@ -20222,7 +20185,6 @@
20222
20185
  "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
20223
20186
  "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
20224
20187
  "dev": true,
20225
- "peer": true,
20226
20188
  "dependencies": {
20227
20189
  "fast-deep-equal": "^3.1.1",
20228
20190
  "fast-json-stable-stringify": "^2.0.0",
@@ -20366,7 +20328,6 @@
20366
20328
  "dev": true,
20367
20329
  "hasInstallScript": true,
20368
20330
  "license": "MIT",
20369
- "peer": true,
20370
20331
  "dependencies": {
20371
20332
  "@aws-sdk/client-api-gateway": "^3.588.0",
20372
20333
  "@aws-sdk/client-cognito-identity-provider": "^3.588.0",
@@ -20466,7 +20427,6 @@
20466
20427
  "resolved": "https://registry.npmjs.org/serverless-offline/-/serverless-offline-13.8.1.tgz",
20467
20428
  "integrity": "sha512-7G/ohXl1qtPIAUHSt3K8mVXWWNdCyQnyIgAixEwBKHllAsbeCjv0/bkz/d0vqIkTGpyfVxnQ5MIhn6u3gZCQbg==",
20468
20429
  "dev": true,
20469
- "peer": true,
20470
20430
  "dependencies": {
20471
20431
  "@aws-sdk/client-lambda": "^3.636.0",
20472
20432
  "@hapi/boom": "^10.0.1",
@@ -22955,7 +22915,6 @@
22955
22915
  "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz",
22956
22916
  "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==",
22957
22917
  "dev": true,
22958
- "peer": true,
22959
22918
  "dependencies": {
22960
22919
  "@cspotcode/source-map-support": "^0.8.0",
22961
22920
  "@tsconfig/node10": "^1.0.7",
@@ -23202,7 +23161,6 @@
23202
23161
  "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
23203
23162
  "dev": true,
23204
23163
  "license": "Apache-2.0",
23205
- "peer": true,
23206
23164
  "bin": {
23207
23165
  "tsc": "bin/tsc",
23208
23166
  "tsserver": "bin/tsserver"
@@ -23448,9 +23406,9 @@
23448
23406
  }
23449
23407
  },
23450
23408
  "node_modules/validator": {
23451
- "version": "13.15.20",
23452
- "resolved": "https://registry.npmjs.org/validator/-/validator-13.15.20.tgz",
23453
- "integrity": "sha512-KxPOq3V2LmfQPP4eqf3Mq/zrT0Dqp2Vmx2Bn285LwVahLc+CsxOM0crBHczm8ijlcjZ0Q5Xd6LW3z3odTPnlrw==",
23409
+ "version": "13.15.26",
23410
+ "resolved": "https://registry.npmjs.org/validator/-/validator-13.15.26.tgz",
23411
+ "integrity": "sha512-spH26xU080ydGggxRyR1Yhcbgx+j3y5jbNXk/8L+iRvdIEQ4uTRH2Sgf2dokud6Q4oAtsbNvJ1Ft+9xmm6IZcA==",
23454
23412
  "license": "MIT",
23455
23413
  "engines": {
23456
23414
  "node": ">= 0.10"
@@ -23553,7 +23511,6 @@
23553
23511
  "integrity": "sha512-QaNKAvGCDRh3wW1dsDjeMdDXwZm2vqq3zn6Pvq4rHOEOGSaUMgOOjG2Y9ZbIGzpfkJk9ZYTHpDqgDfeBDcnLaw==",
23554
23512
  "dev": true,
23555
23513
  "license": "MIT",
23556
- "peer": true,
23557
23514
  "dependencies": {
23558
23515
  "@types/eslint-scope": "^3.7.7",
23559
23516
  "@types/estree": "^1.0.8",
@@ -23998,7 +23955,6 @@
23998
23955
  "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz",
23999
23956
  "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==",
24000
23957
  "dev": true,
24001
- "peer": true,
24002
23958
  "engines": {
24003
23959
  "node": ">=8.3.0"
24004
23960
  },
@@ -55,7 +55,7 @@ export class SampleController {
55
55
  this.logger.debug('commandService:' + this.commandService.tableName)
56
56
  const item = await this.commandService.getItem(detailDto)
57
57
  if (!item) {
58
- throw new NotFoundException()
58
+ throw new NotFoundException('Sample command not found')
59
59
  }
60
60
  this.logger.debug('item:', item)
61
61
  return new SampleCommandEntity(item as SampleCommandEntity)
@@ -66,7 +66,7 @@ export class SampleController {
66
66
  this.logger.debug('dataService:' + this.dataService.tableName)
67
67
  const item = await this.dataService.getItem(detailDto)
68
68
  if (!item) {
69
- throw new NotFoundException()
69
+ throw new NotFoundException('Sample data not found')
70
70
  }
71
71
  this.logger.debug('item:', item)
72
72
  return new SampleDataEntity(item as SampleDataEntity)