@ketrics/ketrics-cli 0.2.3 → 0.3.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 +623 -607
- package/dist/src/version.d.ts +1 -1
- package/dist/src/version.js +1 -1
- package/package.json +1 -1
- package/templates/HelloWorld/README.md +83 -106
- package/templates/HelloWorld/backend/package.json +1 -1
- package/templates/HelloWorld/backend/src/database.ts +108 -0
- package/templates/HelloWorld/backend/src/excel.ts +118 -0
- package/templates/HelloWorld/backend/src/http.ts +22 -0
- package/templates/HelloWorld/backend/src/index.ts +105 -29
- package/templates/HelloWorld/backend/src/jobs.ts +47 -0
- package/templates/HelloWorld/backend/src/messages.ts +59 -0
- package/templates/HelloWorld/backend/src/pdf.ts +212 -0
- package/templates/HelloWorld/backend/src/secrets.ts +21 -14
- package/templates/HelloWorld/backend/src/volumes.ts +107 -0
- package/templates/HelloWorld/frontend/package.json +1 -3
- package/templates/HelloWorld/frontend/src/App.css +62 -37
- package/templates/HelloWorld/frontend/src/App.tsx +131 -111
- package/templates/HelloWorld/frontend/src/services/index.ts +11 -11
- package/templates/HelloWorld/tests/test.createInvoicePdf.json +18 -0
- package/templates/HelloWorld/tests/{test.getSecretWithoutGrant.json → test.createSimplePdf.json} +4 -2
- package/templates/HelloWorld/tests/test.createSpreadsheet.json +11 -0
- package/templates/HelloWorld/tests/test.echo.json +2 -2
- package/templates/HelloWorld/tests/test.fetchExternalApi.json +13 -0
- package/templates/HelloWorld/tests/test.getSecret.json +5 -1
- package/templates/HelloWorld/tests/test.info.json +3 -1
- package/templates/HelloWorld/tests/test.listFiles.json +13 -0
- package/templates/HelloWorld/tests/{test.echo2.json → test.queryUsers.json} +3 -3
- package/templates/HelloWorld/tests/{test.greet.json → test.readFile.json} +2 -2
- package/templates/HelloWorld/tests/{test.testWriteFileWithoutVolumeGrant.json → test.saveFile.json} +4 -2
- package/templates/HelloWorld/tests/test.sendNotification.json +14 -0
- package/templates/HelloWorld/backend/src/volume.ts +0 -55
package/README.md
CHANGED
|
@@ -1,746 +1,762 @@
|
|
|
1
1
|
# Ketrics CLI
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
A command-line tool for creating, building, validating, and deploying applications to the Ketrics serverless platform.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Overview
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
The Ketrics CLI (`@ketrics/ketrics-cli`) is a developer tool that streamlines the full lifecycle of Ketrics tenant applications—from project scaffolding to production deployment. It abstracts the complexity of packaging frontend and backend code into deployment bundles and handles authentication with the Ketrics Tenant API API.
|
|
10
|
-
|
|
11
|
-
### Architecture Position
|
|
12
|
-
|
|
13
|
-
```
|
|
14
|
-
┌──────────────────────────────────────────────────────────────────┐
|
|
15
|
-
│ Developer Workstation │
|
|
16
|
-
│ ┌─────────────┐ ┌────────────────┐ ┌────────────────┐ │
|
|
17
|
-
│ │ Application │────▶│ Ketrics CLI │────▶│ Tenant API │ │
|
|
18
|
-
│ │ Source │ │ (build & zip) │ │ API │ │
|
|
19
|
-
│ └─────────────┘ └────────────────┘ └────────────────┘ │
|
|
20
|
-
└──────────────────────────────────────────────────────────────────┘
|
|
21
|
-
│
|
|
22
|
-
│ Presigned URL
|
|
23
|
-
▼
|
|
24
|
-
┌──────────────┐
|
|
25
|
-
│ S3 │
|
|
26
|
-
│ (code-bundle)│
|
|
27
|
-
└──────────────┘
|
|
28
|
-
│
|
|
29
|
-
│ S3 Event Trigger
|
|
30
|
-
▼
|
|
31
|
-
┌──────────────┐ ┌──────────────┐
|
|
32
|
-
│ Deployment │────▶│ EFS │
|
|
33
|
-
│ Lambda │ │ (extracted) │
|
|
34
|
-
└──────────────┘ └──────────────┘
|
|
35
|
-
│
|
|
36
|
-
▼
|
|
37
|
-
┌──────────────┐
|
|
38
|
-
│ Data Plane │
|
|
39
|
-
│ (runtime) │
|
|
40
|
-
└──────────────┘
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
The CLI sits at the beginning of the deployment pipeline:
|
|
44
|
-
|
|
45
|
-
1. Developers write frontend (React) and backend (TypeScript handlers) code
|
|
46
|
-
2. CLI builds both, packages them into a single ZIP archive
|
|
47
|
-
3. CLI uploads the ZIP to S3 via a presigned URL obtained from Tenant API API
|
|
48
|
-
4. Downstream systems (Deployment Lambda) extract the bundle to EFS for Data Plane execution
|
|
7
|
+
The Ketrics CLI (`@ketrics/ketrics-cli`) is a TypeScript-based command-line interface that enables developers to manage their Ketrics applications across the complete application lifecycle. It fits into the Ketrics platform ecosystem as the primary interface for local development and deployment workflows.
|
|
49
8
|
|
|
50
9
|
### Key Responsibilities
|
|
51
10
|
|
|
52
|
-
- **
|
|
53
|
-
- **
|
|
54
|
-
- **
|
|
55
|
-
- **
|
|
56
|
-
- **
|
|
57
|
-
- **
|
|
58
|
-
- **
|
|
59
|
-
|
|
60
|
-
### Boundaries
|
|
61
|
-
|
|
62
|
-
The CLI does **not**:
|
|
63
|
-
|
|
64
|
-
- Execute application code (that's the Data Plane's role)
|
|
65
|
-
- Manage infrastructure (handled by Terraform)
|
|
66
|
-
- Handle tenant/user management (Tenant API API's domain)
|
|
67
|
-
- Extract bundles to EFS (Deployment Lambda's responsibility)
|
|
68
|
-
|
|
69
|
-
---
|
|
70
|
-
|
|
71
|
-
## 2. Business Logic
|
|
72
|
-
|
|
73
|
-
### Problem Statement
|
|
74
|
-
|
|
75
|
-
Developers building Ketrics applications need a consistent, reliable way to:
|
|
76
|
-
|
|
77
|
-
1. Bootstrap new projects with correct structure and configuration
|
|
78
|
-
2. Build and package both frontend and backend code
|
|
79
|
-
3. Deploy code bundles to the platform with proper authentication
|
|
80
|
-
4. Test deployed functions without building custom HTTP clients
|
|
81
|
-
|
|
82
|
-
### Core Workflows
|
|
83
|
-
|
|
84
|
-
#### Scaffold Workflow (`ketrics create`)
|
|
85
|
-
|
|
86
|
-
```
|
|
87
|
-
1. Validate app name (alphanumeric, starts with letter)
|
|
88
|
-
2. Check destination directory doesn't exist
|
|
89
|
-
3. List available templates from bundled /templates directory
|
|
90
|
-
4. Interactive template selection (or use --template flag)
|
|
91
|
-
5. Copy template files to new directory
|
|
92
|
-
6. Update app name in ketrics.config.json, frontend/package.json, backend/package.json
|
|
93
|
-
```
|
|
94
|
-
|
|
95
|
-
#### Build Workflow (`ketrics build`)
|
|
96
|
-
|
|
97
|
-
```
|
|
98
|
-
1. Validate frontend/ directory exists with node_modules
|
|
99
|
-
2. Validate backend/ directory exists with node_modules
|
|
100
|
-
3. Run `npm run build` in frontend/ (expects dist/ output)
|
|
101
|
-
4. Run `npm run build` in backend/ (expects dist/ output)
|
|
102
|
-
5. Verify both dist/ directories were created
|
|
103
|
-
```
|
|
104
|
-
|
|
105
|
-
#### Deploy Workflow (`ketrics deploy`)
|
|
106
|
-
|
|
107
|
-
```
|
|
108
|
-
1. Load .env file and validate required KETRICS_* variables
|
|
109
|
-
2. Validate deployment token format (must start with "ktd_")
|
|
110
|
-
3. Execute full build workflow (frontend + backend)
|
|
111
|
-
4. Create ZIP archive:
|
|
112
|
-
- frontend/ folder containing frontend/dist/* contents
|
|
113
|
-
- backend/ folder containing backend/dist/* contents
|
|
114
|
-
5. Call Tenant API API: POST /tenants/{tenantId}/applications/{appId}/deploy
|
|
115
|
-
6. Receive presigned S3 URL with deploymentId
|
|
116
|
-
7. PUT ZIP buffer to presigned URL
|
|
117
|
-
8. Display success with deploymentId, file count, size, duration
|
|
118
|
-
```
|
|
119
|
-
|
|
120
|
-
#### Validate Workflow (`ketrics validate`)
|
|
121
|
-
|
|
122
|
-
```
|
|
123
|
-
1. Check ketrics.config.json exists and is valid JSON
|
|
124
|
-
2. Validate against ketricsConfigSchema (Zod)
|
|
125
|
-
3. Check .env file exists
|
|
126
|
-
4. Validate KETRICS_* variables against envConfigSchema
|
|
127
|
-
5. Report errors and warnings (e.g., token format, empty exclude patterns)
|
|
128
|
-
```
|
|
129
|
-
|
|
130
|
-
#### Run Workflow (`ketrics run <json-file>`)
|
|
131
|
-
|
|
132
|
-
```
|
|
133
|
-
1. Load .env file (requires KETRICS_AUTH_TOKEN and KETRICS_RUNTIME_URL)
|
|
134
|
-
2. Parse JSON file against runFileSchema
|
|
135
|
-
3. Interpolate template variables: {{tenantId}}, {{applicationId}}, {{token}}
|
|
136
|
-
4. Construct full URL: KETRICS_RUNTIME_URL + interpolated endpoint
|
|
137
|
-
5. Execute HTTP request (GET/POST/PUT/DELETE/PATCH)
|
|
138
|
-
6. Display formatted response with status and body
|
|
139
|
-
```
|
|
140
|
-
|
|
141
|
-
### Business Rules
|
|
142
|
-
|
|
143
|
-
| Rule | Implementation |
|
|
144
|
-
| ------------------------------------------ | ----------------------------------------------- |
|
|
145
|
-
| App names must be valid identifiers | Regex: `^[a-zA-Z][a-zA-Z0-9_-]*$` |
|
|
146
|
-
| Deployment tokens must have correct prefix | Token must start with `ktd_` |
|
|
147
|
-
| Tenant/Application IDs must be UUIDs | Zod `.uuid()` validation |
|
|
148
|
-
| API URL must be valid HTTPS URL | Zod `.url()` validation |
|
|
149
|
-
| Both frontend and backend must build | Both `dist/` directories must exist after build |
|
|
150
|
-
| Templates must have ketrics.config.json | Templates without config are skipped |
|
|
151
|
-
|
|
152
|
-
### Input/Output Expectations
|
|
153
|
-
|
|
154
|
-
**Deploy Input:**
|
|
155
|
-
|
|
156
|
-
- `.env` file with `KETRICS_TOKEN`, `KETRICS_API_URL`, `KETRICS_TENANT_ID`, `KETRICS_APPLICATION_ID`
|
|
157
|
-
- `frontend/` directory with `package.json` and `node_modules`
|
|
158
|
-
- `backend/` directory with `package.json` and `node_modules`
|
|
159
|
-
|
|
160
|
-
**Deploy Output:**
|
|
161
|
-
|
|
162
|
-
- ZIP file uploaded to S3 with structure:
|
|
163
|
-
```
|
|
164
|
-
bundle.zip
|
|
165
|
-
├── frontend/
|
|
166
|
-
│ ├── index.html
|
|
167
|
-
│ └── assets/
|
|
168
|
-
│ ├── index-*.js
|
|
169
|
-
│ └── index-*.css
|
|
170
|
-
└── backend/
|
|
171
|
-
├── index.js
|
|
172
|
-
└── index.d.ts
|
|
173
|
-
```
|
|
174
|
-
|
|
175
|
-
### Edge Cases Handled
|
|
11
|
+
- **Application Creation**: Bootstrap new projects from predefined templates
|
|
12
|
+
- **Build Orchestration**: Compile frontend and backend applications before deployment
|
|
13
|
+
- **Configuration Management**: Load and validate project configuration and environment variables
|
|
14
|
+
- **Package Bundling**: Create optimized ZIP archives with proper file structure and compression
|
|
15
|
+
- **Deployment Automation**: Coordinate the deploy process including API communication and S3 uploads
|
|
16
|
+
- **Configuration Validation**: Verify configuration files and environment setup before operations
|
|
17
|
+
- **Request Execution**: Execute HTTP API requests with variable interpolation and templating
|
|
176
18
|
|
|
177
|
-
|
|
178
|
-
- **node_modules missing**: Build command detects and prompts user to run `npm install`
|
|
179
|
-
- **Empty dist directories**: Error thrown if no files found after build
|
|
180
|
-
- **Network failures**: Axios timeout (30s API, 5min upload) with specific error messages
|
|
181
|
-
- **Expired presigned URL**: Clear error message on 403/400 from S3
|
|
182
|
-
- **Invalid JSON in config files**: Parse errors with file path and position
|
|
19
|
+
### Architecture Boundaries
|
|
183
20
|
|
|
184
|
-
|
|
21
|
+
This component operates as a standalone CLI tool that:
|
|
22
|
+
- Does NOT handle cloud infrastructure provisioning (delegated to Ketrics backend)
|
|
23
|
+
- Does NOT manage authentication beyond token validation (relies on KETRICS_TOKEN format)
|
|
24
|
+
- Does NOT execute or monitor running applications (delegated to Ketrics platform)
|
|
25
|
+
- Focuses exclusively on local operations and integration with Ketrics deployment APIs
|
|
185
26
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
### Technology Stack
|
|
189
|
-
|
|
190
|
-
| Component | Technology | Version |
|
|
191
|
-
| --------------------- | ----------------- | -------- |
|
|
192
|
-
| Runtime | Node.js | >=24.0.0 |
|
|
193
|
-
| Language | TypeScript | ^5.3.3 |
|
|
194
|
-
| CLI Framework | Commander.js | ^12.0.0 |
|
|
195
|
-
| HTTP Client | Axios | ^1.6.0 |
|
|
196
|
-
| Schema Validation | Zod | ^3.22.4 |
|
|
197
|
-
| ZIP Creation | Archiver | ^6.0.1 |
|
|
198
|
-
| File Patterns | glob | ^10.3.0 |
|
|
199
|
-
| Interactive Prompts | @inquirer/prompts | ^7.10.1 |
|
|
200
|
-
| Console Styling | Chalk | ^4.1.2 |
|
|
201
|
-
| Loading Spinners | ora | ^5.4.1 |
|
|
202
|
-
| Environment Variables | dotenv | ^16.3.1 |
|
|
203
|
-
|
|
204
|
-
### File Structure
|
|
27
|
+
### Project Structure
|
|
205
28
|
|
|
206
29
|
```
|
|
207
30
|
ketrics-cli/
|
|
208
31
|
├── bin/
|
|
209
|
-
│ └── ketrics.ts # CLI entry point
|
|
32
|
+
│ └── ketrics.ts # CLI entry point
|
|
210
33
|
├── src/
|
|
211
|
-
│ ├── cli.ts # Commander
|
|
212
|
-
│ ├── index.ts #
|
|
34
|
+
│ ├── cli.ts # Commander.js setup and command definitions
|
|
35
|
+
│ ├── index.ts # Public API exports
|
|
36
|
+
│ ├── version.ts # Auto-generated version
|
|
37
|
+
│ ├── types/
|
|
38
|
+
│ │ └── index.ts # Zod schemas and TypeScript interfaces
|
|
213
39
|
│ ├── commands/
|
|
214
|
-
│ │ ├── create.ts #
|
|
215
|
-
│ │ ├── build.ts #
|
|
216
|
-
│ │ ├── deploy.ts #
|
|
217
|
-
│ │ ├── validate.ts #
|
|
218
|
-
│ │ └── run.ts #
|
|
40
|
+
│ │ ├── create.ts # Bootstrap new project from template
|
|
41
|
+
│ │ ├── build.ts # Build frontend/backend
|
|
42
|
+
│ │ ├── deploy.ts # Deploy application
|
|
43
|
+
│ │ ├── validate.ts # Validate configuration
|
|
44
|
+
│ │ └── run.ts # Execute API requests
|
|
219
45
|
│ ├── services/
|
|
220
|
-
│ │ ├── api-client.ts # HTTP client for Tenant API API
|
|
221
|
-
│ │ ├── build-service.ts # npm build execution and validation
|
|
222
46
|
│ │ ├── config-service.ts # Load/validate ketrics.config.json and .env
|
|
223
|
-
│ │ ├──
|
|
224
|
-
│ │ ├──
|
|
225
|
-
│ │
|
|
226
|
-
│ ├──
|
|
227
|
-
│ │ └──
|
|
47
|
+
│ │ ├── build-service.ts # Orchestrate npm build for frontend/backend
|
|
48
|
+
│ │ ├── api-client.ts # HTTP communication with Ketrics API
|
|
49
|
+
│ │ ├── zip-service.ts # ZIP archive creation and compression
|
|
50
|
+
│ │ ├── upload-service.ts # S3 upload via presigned URLs
|
|
51
|
+
│ │ └── template-service.ts # Template discovery and copying
|
|
228
52
|
│ └── utils/
|
|
229
|
-
│ ├── logger.ts # Colored console output
|
|
230
|
-
│ └── spinner.ts # Loading
|
|
53
|
+
│ ├── logger.ts # Colored console output
|
|
54
|
+
│ └── spinner.ts # Loading indicators
|
|
231
55
|
├── templates/
|
|
232
|
-
│ └──
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
│ └── tests/ # Sample run files for ketrics run
|
|
237
|
-
├── package.json
|
|
238
|
-
└── tsconfig.json
|
|
56
|
+
│ └── HelloWorld/ # Example template for project scaffolding
|
|
57
|
+
├── package.json # NPM package configuration
|
|
58
|
+
├── tsconfig.json # TypeScript configuration
|
|
59
|
+
└── dist/ # Compiled JavaScript (generated)
|
|
239
60
|
```
|
|
240
61
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
#### `src/cli.ts`
|
|
62
|
+
## Business Logic
|
|
244
63
|
|
|
245
|
-
|
|
246
|
-
export function createCLI(): Command;
|
|
247
|
-
```
|
|
64
|
+
### Problem Statement
|
|
248
65
|
|
|
249
|
-
|
|
66
|
+
Developers need a consistent way to:
|
|
67
|
+
1. Create new Ketrics applications with proper structure
|
|
68
|
+
2. Build applications locally before deployment
|
|
69
|
+
3. Package and upload applications to Ketrics infrastructure
|
|
70
|
+
4. Test API integrations without manual HTTP requests
|
|
71
|
+
5. Validate configuration before attempting deployments
|
|
250
72
|
|
|
251
|
-
|
|
73
|
+
### Core Workflows
|
|
252
74
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
75
|
+
#### 1. Application Creation (`ketrics create`)
|
|
76
|
+
|
|
77
|
+
**Inputs**: Application name, optional template name
|
|
78
|
+
**Process**:
|
|
79
|
+
1. Validate app name (alphanumeric, hyphens, underscores; must start with letter)
|
|
80
|
+
2. Discover available templates from the `templates/` directory
|
|
81
|
+
3. Prompt for template selection (interactive or via `--template` flag)
|
|
82
|
+
4. Create application directory
|
|
83
|
+
5. Copy template files recursively
|
|
84
|
+
6. Update app name in `ketrics.config.json`, `frontend/package.json`, and `backend/package.json`
|
|
85
|
+
|
|
86
|
+
**Outputs**: New project directory with template structure
|
|
87
|
+
**Exit on Error**: Name validation failure, template not found, directory exists
|
|
88
|
+
|
|
89
|
+
#### 2. Build Process (`ketrics build`)
|
|
90
|
+
|
|
91
|
+
**Inputs**: Current working directory must contain `frontend/` and `backend/` subdirectories
|
|
92
|
+
**Process**:
|
|
93
|
+
1. Validate both directories exist with `node_modules` installed
|
|
94
|
+
2. Execute `npm run build` in `frontend/` directory
|
|
95
|
+
3. Validate `frontend/dist/` was created
|
|
96
|
+
4. Execute `npm run build` in `backend/` directory
|
|
97
|
+
5. Validate `backend/dist/` was created
|
|
98
|
+
6. Report dist paths to user
|
|
99
|
+
|
|
100
|
+
**Outputs**: Built artifacts in `frontend/dist/` and `backend/dist/`
|
|
101
|
+
**Exit on Error**: Missing directories, missing node_modules, build failure, missing dist output
|
|
102
|
+
|
|
103
|
+
#### 3. Deployment Process (`ketrics deploy`)
|
|
104
|
+
|
|
105
|
+
**Inputs**: Working directory with built `frontend/dist/` and `backend/dist/`, `.env` with credentials
|
|
106
|
+
**Process**:
|
|
107
|
+
1. Load and validate environment configuration
|
|
108
|
+
2. Validate token format (must start with `ktd_`)
|
|
109
|
+
3. Build frontend and backend (calls buildAll)
|
|
110
|
+
4. Collect files from both dist directories into a structured ZIP
|
|
111
|
+
5. Create presigned S3 URL via Ketrics API (`POST /tenants/{id}/applications/{id}/deploy`)
|
|
112
|
+
6. Upload ZIP buffer to S3 via presigned URL
|
|
113
|
+
7. Return deployment ID and summary
|
|
114
|
+
|
|
115
|
+
**Outputs**: Deployment confirmation with ID, file count, and timing
|
|
116
|
+
**Special Mode - Dry Run** (`--dry-run`): Shows files to be deployed without uploading
|
|
117
|
+
**Exit on Error**: Config loading failure, token validation, build failure, API error, upload failure
|
|
118
|
+
|
|
119
|
+
#### 4. Configuration Validation (`ketrics validate`)
|
|
120
|
+
|
|
121
|
+
**Inputs**: Optional paths to `ketrics.config.json` and `.env`
|
|
122
|
+
**Process**:
|
|
123
|
+
1. Check file existence
|
|
124
|
+
2. Parse JSON and validate against schemas
|
|
125
|
+
3. Check token format (warning only)
|
|
126
|
+
4. Collect all errors and warnings
|
|
127
|
+
5. Report validation results
|
|
128
|
+
|
|
129
|
+
**Outputs**: List of errors (blocking) and warnings (informational)
|
|
130
|
+
**Exit on Error**: Any validation errors present
|
|
131
|
+
|
|
132
|
+
#### 5. API Request Execution (`ketrics run`)
|
|
133
|
+
|
|
134
|
+
**Inputs**: JSON configuration file with endpoint, method, headers, body
|
|
135
|
+
**Process**:
|
|
136
|
+
1. Load environment configuration (requires `KETRICS_AUTH_TOKEN` and `KETRICS_RUNTIME_URL`)
|
|
137
|
+
2. Parse JSON run file (validates schema)
|
|
138
|
+
3. Create variable map from environment (tenantId, applicationId, token)
|
|
139
|
+
4. Interpolate all template variables: `{{tenantId}}`, `{{applicationId}}`, `{{token}}`
|
|
140
|
+
5. Construct full URL from runtime URL + interpolated endpoint
|
|
141
|
+
6. Execute HTTP request with interpolated headers/body
|
|
142
|
+
7. Display request and response details
|
|
143
|
+
|
|
144
|
+
**Outputs**: HTTP response status and body
|
|
145
|
+
**Exit on Error**: Missing env vars, invalid JSON, connection refused, timeout
|
|
256
146
|
|
|
257
|
-
|
|
147
|
+
### Business Rules
|
|
258
148
|
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
149
|
+
- **Token Format**: Deployment tokens must start with `ktd_` (validated before API calls)
|
|
150
|
+
- **App Name Format**: Must start with letter, contain only alphanumeric/hyphens/underscores
|
|
151
|
+
- **Build Prerequisites**: Both frontend and backend must have `node_modules` before building
|
|
152
|
+
- **Dist Structure**: Frontend builds to `frontend/dist/`, backend builds to `backend/dist/`
|
|
153
|
+
- **File Patterns**: Include/exclude patterns use glob syntax for flexible file selection
|
|
154
|
+
- **ZIP Compression**: Level 9 compression (maximum) used for all deployments
|
|
155
|
+
- **Request Timeout**: API calls timeout at 30 seconds, S3 uploads at 5 minutes
|
|
156
|
+
- **Variable Interpolation**: All string values in run JSON are scanned for `{{varName}}` patterns
|
|
262
157
|
|
|
263
|
-
|
|
158
|
+
### Input/Output Expectations
|
|
264
159
|
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
160
|
+
**Configuration Files**:
|
|
161
|
+
- `ketrics.config.json`: JSON with name, version, actions, entry, include/exclude patterns
|
|
162
|
+
- `.env`: Key=value format with KETRICS_* variables
|
|
163
|
+
- Run JSON: POST/PUT/DELETE/PATCH/GET requests with endpoint, headers, body
|
|
268
164
|
|
|
269
|
-
|
|
165
|
+
**Exit Codes**:
|
|
166
|
+
- `0`: Successful execution
|
|
167
|
+
- `1`: Any error condition (validation failure, build failure, API error, etc.)
|
|
270
168
|
|
|
271
|
-
|
|
169
|
+
## Technical Details
|
|
272
170
|
|
|
273
|
-
|
|
274
|
-
export function buildAll(projectDir: string): BuildResult;
|
|
275
|
-
```
|
|
171
|
+
### Technology Stack
|
|
276
172
|
|
|
277
|
-
|
|
173
|
+
- **Runtime**: Node.js 24.0.0+ (specified in package.json engines)
|
|
174
|
+
- **Language**: TypeScript 5.3.3 with strict type checking
|
|
175
|
+
- **CLI Framework**: Commander.js 12.0.0 (argument parsing and command structure)
|
|
176
|
+
- **HTTP Client**: Axios 1.6.0 (with timeout and error handling)
|
|
177
|
+
- **Validation**: Zod 3.22.4 (schema validation for configs and responses)
|
|
178
|
+
- **UI/UX**:
|
|
179
|
+
- Chalk 4.1.2 (colored terminal output)
|
|
180
|
+
- Ora 5.4.1 (loading spinners)
|
|
181
|
+
- @inquirer/prompts 7.10.1 (interactive prompts)
|
|
182
|
+
- **File Operations**: Native Node.js fs and path modules
|
|
183
|
+
- **Compression**: Archiver 6.0.1 (ZIP creation with streaming)
|
|
184
|
+
- **Pattern Matching**: Glob 10.3.0 (file selection with include/exclude)
|
|
185
|
+
- **Environment Loading**: dotenv 16.3.1 (.env file parsing)
|
|
186
|
+
- **Process Execution**: Native Node.js child_process (execSync for npm commands)
|
|
187
|
+
|
|
188
|
+
### Dependencies Analysis
|
|
278
189
|
|
|
279
|
-
```
|
|
280
|
-
|
|
190
|
+
```json
|
|
191
|
+
{
|
|
192
|
+
"core-cli": ["commander@12.0.0"],
|
|
193
|
+
"validation": ["zod@3.22.4"],
|
|
194
|
+
"http": ["axios@1.6.0"],
|
|
195
|
+
"compression": ["archiver@6.0.1"],
|
|
196
|
+
"file-patterns": ["glob@10.3.0"],
|
|
197
|
+
"environment": ["dotenv@16.3.1"],
|
|
198
|
+
"ui": ["chalk@4.1.2", "ora@5.4.1", "@inquirer/prompts@7.10.1"],
|
|
199
|
+
"dev-dependencies": ["typescript@5.3.3", "ts-node@1.7.1", "@types/*"]
|
|
200
|
+
}
|
|
281
201
|
```
|
|
282
202
|
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
#### `src/services/zip-service.ts`
|
|
286
|
-
|
|
287
|
-
```typescript
|
|
288
|
-
export async function createDeploymentZipBundle(
|
|
289
|
-
frontendDistPath: string,
|
|
290
|
-
backendDistPath: string,
|
|
291
|
-
): Promise<{ buffer: Buffer; files: FileInfo[]; totalSourceSize: number; zipSize: number }>;
|
|
292
|
-
```
|
|
203
|
+
### File Descriptions
|
|
293
204
|
|
|
294
|
-
|
|
205
|
+
**bin/ketrics.ts**
|
|
206
|
+
- Entry point executable (shebang for direct CLI usage)
|
|
207
|
+
- Instantiates CLI via `createCLI()` and parses process.argv
|
|
208
|
+
- Results in `dist/bin/ketrics.js` which is referenced in package.json bin field
|
|
295
209
|
|
|
296
|
-
|
|
210
|
+
**src/cli.ts**
|
|
211
|
+
- Configures Commander.js program with CLI name, version, and help text
|
|
212
|
+
- Defines 5 commands: create, build, deploy, validate, run
|
|
213
|
+
- Maps command arguments/options to handler functions
|
|
214
|
+
- Exported as `createCLI()` function
|
|
297
215
|
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
216
|
+
**src/commands/*.ts**
|
|
217
|
+
- Each file exports single command handler function
|
|
218
|
+
- Validates inputs, orchestrates service layer calls
|
|
219
|
+
- Handles errors and formats output via logger
|
|
220
|
+
- No business logic—purely orchestration and user interaction
|
|
301
221
|
|
|
302
|
-
|
|
222
|
+
**src/services/*.ts**
|
|
303
223
|
|
|
304
|
-
|
|
224
|
+
- **config-service.ts**: Zod validation, dotenv parsing, schema enforcement. Functions: `loadEnvConfig()`, `loadKetricsConfig()`, `validateConfig()`
|
|
225
|
+
- **build-service.ts**: npm script execution via child_process. Functions: `buildAll()`, `runBuild()`, `validateBuildDirectory()`, `validateDistDirectory()`
|
|
226
|
+
- **api-client.ts**: Axios POST to `/tenants/{id}/applications/{id}/deploy`. Returns presigned URL and deployment ID. Error handling for 401/403/404 status codes.
|
|
227
|
+
- **zip-service.ts**: Archiver for ZIP creation, glob for file collection, streaming compression. Dual functions for config-based and directory-based bundling.
|
|
228
|
+
- **upload-service.ts**: Axios PUT to S3 presigned URL with binary data. 5-minute timeout for large uploads. Error handling for 400/403/413 status codes.
|
|
229
|
+
- **template-service.ts**: Directory traversal to discover templates, recursive copying, JSON field updates. Functions: `getAvailableTemplates()`, `copyTemplate()`, `updateAppName()`
|
|
305
230
|
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
231
|
+
**src/types/index.ts**
|
|
232
|
+
- Zod schemas for runtime validation: `ketricsConfigSchema`, `envConfigSchema`, `runFileSchema`, `runEnvConfigSchema`
|
|
233
|
+
- TypeScript interfaces derived from schemas via `z.infer<T>`
|
|
234
|
+
- API response types: `DeployResponse` (presigned URL data)
|
|
235
|
+
- Supporting types: `FileInfo`, `ValidationResult`, `TemplateInfo`
|
|
309
236
|
|
|
310
|
-
|
|
237
|
+
**src/utils/logger.ts**
|
|
238
|
+
- Singleton object with named methods: `info()`, `success()`, `warn()`, `error()`, `log()`, `newline()`, `header()`, `keyValue()`, `indent()`, `file()`, `box()`
|
|
239
|
+
- Uses chalk for ANSI color codes
|
|
240
|
+
- Replaces raw `console.log()` throughout codebase
|
|
311
241
|
|
|
312
|
-
|
|
242
|
+
**src/utils/spinner.ts**
|
|
243
|
+
- `createSpinner(text)`: Ora spinner instance
|
|
244
|
+
- `withSpinner<T>(text, operation, successText)`: Wraps async operation with spinner, handles errors, returns result
|
|
245
|
+
- Provides visual feedback for long-running operations
|
|
313
246
|
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
247
|
+
**src/version.ts**
|
|
248
|
+
- Single auto-generated export: `VERSION = "0.2.3"`
|
|
249
|
+
- Generated by `scripts/generate-version.js` during build
|
|
250
|
+
- Referenced in cli.ts for `--version` flag
|
|
317
251
|
|
|
318
|
-
|
|
252
|
+
### Configuration Options and Environment Variables
|
|
319
253
|
|
|
254
|
+
**ketrics.config.json Schema** (Zod validation):
|
|
320
255
|
```typescript
|
|
321
|
-
|
|
256
|
+
{
|
|
257
|
+
name: string, // Project name (required, min 1 char)
|
|
258
|
+
version: string, // Semver format e.g. "1.0.0" (required)
|
|
259
|
+
description?: string, // Optional project description
|
|
260
|
+
runtime: "nodejs18" | "nodejs20" | "static", // Default: "nodejs18"
|
|
261
|
+
actions: string[], // At least 1 action name (required)
|
|
262
|
+
entry: string, // Entry point file (required)
|
|
263
|
+
include: string[], // Glob patterns to include (required, min 1)
|
|
264
|
+
exclude: string[] // Glob patterns to exclude (default: [])
|
|
265
|
+
}
|
|
322
266
|
```
|
|
323
267
|
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
```typescript
|
|
327
|
-
export function updateAppName(projectDir: string, appName: string): void;
|
|
268
|
+
**Environment Variables** (loaded from .env):
|
|
328
269
|
```
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
```typescript
|
|
337
|
-
const ketricsConfigSchema = z.object({
|
|
338
|
-
name: z.string().min(1),
|
|
339
|
-
version: z.string().regex(/^\d+\.\d+\.\d+$/), // semver
|
|
340
|
-
description: z.string().optional(),
|
|
341
|
-
runtime: z.enum(["nodejs18", "nodejs20", "static"]).default("nodejs18"),
|
|
342
|
-
actions: z.array(z.string()).min(1),
|
|
343
|
-
entry: z.string().min(1),
|
|
344
|
-
include: z.array(z.string()).min(1),
|
|
345
|
-
exclude: z.array(z.string()).default([]),
|
|
346
|
-
});
|
|
270
|
+
KETRICS_TOKEN # Deploy token starting with "ktd_" (required)
|
|
271
|
+
KETRICS_API_URL # Ketrics API base URL (required, must be valid URL)
|
|
272
|
+
KETRICS_TENANT_ID # Tenant UUID (required, UUID format)
|
|
273
|
+
KETRICS_APPLICATION_ID # Application UUID (required, UUID format)
|
|
274
|
+
KETRICS_AUTH_TOKEN # Runtime auth token (optional, required for run command)
|
|
275
|
+
KETRICS_RUNTIME_URL # Runtime API URL (optional, required for run command, must be URL)
|
|
347
276
|
```
|
|
348
277
|
|
|
349
|
-
#### Environment Variables
|
|
350
|
-
|
|
351
|
-
| Variable | Required | Description |
|
|
352
|
-
| ------------------------ | --------- | ------------------------------------------------------------- |
|
|
353
|
-
| `KETRICS_TOKEN` | Yes | Deployment token (format: `ktd_{id}_{secret}`) |
|
|
354
|
-
| `KETRICS_API_URL` | Yes | Tenant API API URL (e.g., `https://api.ketrics.io/api/v1`) |
|
|
355
|
-
| `KETRICS_TENANT_ID` | Yes | Tenant UUID |
|
|
356
|
-
| `KETRICS_APPLICATION_ID` | Yes | Application UUID |
|
|
357
|
-
| `KETRICS_AUTH_TOKEN` | For `run` | User auth token for runtime API calls |
|
|
358
|
-
| `KETRICS_RUNTIME_URL` | For `run` | Data Plane runtime URL |
|
|
359
|
-
|
|
360
278
|
### External Integrations
|
|
361
279
|
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
280
|
+
**Ketrics Tenant API**
|
|
281
|
+
- Endpoint: `POST /tenants/{KETRICS_TENANT_ID}/applications/{KETRICS_APPLICATION_ID}/deploy`
|
|
282
|
+
- Authentication: Bearer token (KETRICS_TOKEN)
|
|
283
|
+
- Request: Empty POST body
|
|
284
|
+
- Response: `{ success: boolean, data: { uploadUrl, deploymentId, s3Key, expiresAt, expiresInSeconds } }`
|
|
285
|
+
- Errors: 401 (bad token), 403 (no access), 404 (app not found)
|
|
286
|
+
|
|
287
|
+
**AWS S3** (via presigned URL)
|
|
288
|
+
- Method: PUT request to presigned URL from deploy response
|
|
289
|
+
- Headers: `Content-Type: application/zip`, `Content-Length: <bytes>`
|
|
290
|
+
- Body: Raw ZIP buffer (binary)
|
|
291
|
+
- Timeout: 300 seconds (5 minutes)
|
|
292
|
+
- Errors: 400 (expired URL), 403 (URL reused), 413 (file too large)
|
|
293
|
+
|
|
294
|
+
**Ketrics Runtime API** (for run command)
|
|
295
|
+
- Base URL: KETRICS_RUNTIME_URL from .env
|
|
296
|
+
- Endpoint: User-specified path in run JSON
|
|
297
|
+
- Authentication: Bearer token (KETRICS_AUTH_TOKEN in Authorization header)
|
|
298
|
+
- Methods: GET, POST, PUT, DELETE, PATCH
|
|
299
|
+
- Timeout: 30 seconds
|
|
300
|
+
- Response: Any JSON/text (no validation)
|
|
301
|
+
|
|
302
|
+
## Data Flow
|
|
303
|
+
|
|
304
|
+
### Deploy Command Data Flow
|
|
305
|
+
|
|
306
|
+
```
|
|
307
|
+
User Input (--env flag, working directory)
|
|
308
|
+
↓
|
|
309
|
+
Load .env → dotenv.parse() → Zod validation → EnvConfig object
|
|
310
|
+
↓
|
|
311
|
+
Build frontend → execSync('npm run build') → frontend/dist/
|
|
312
|
+
↓
|
|
313
|
+
Build backend → execSync('npm run build') → backend/dist/
|
|
314
|
+
↓
|
|
315
|
+
Collect files → fs.readdirSync() recursive → FileInfo[] array
|
|
316
|
+
↓
|
|
317
|
+
Create ZIP → Archiver stream + glob + compression → Buffer
|
|
318
|
+
↓
|
|
319
|
+
API Call → axios.post() → Ketrics /deploy endpoint → DeployResponse
|
|
320
|
+
↓
|
|
321
|
+
S3 Upload → axios.put() → presigned URL + ZIP buffer → AWS S3
|
|
322
|
+
↓
|
|
323
|
+
Result → logger.box() → Deployment ID displayed to user
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
### Create Command Data Flow
|
|
327
|
+
|
|
328
|
+
```
|
|
329
|
+
User Input (app name, optional --template)
|
|
330
|
+
↓
|
|
331
|
+
Validate name → Regex check → boolean result
|
|
332
|
+
↓
|
|
333
|
+
Discover templates → fs.readdirSync(templates/) → TemplateInfo[]
|
|
334
|
+
↓
|
|
335
|
+
Prompt selection → inquirer.select() → User choice or --template flag
|
|
336
|
+
↓
|
|
337
|
+
Copy template → Recursive fs.copyFileSync() → New directory tree
|
|
338
|
+
↓
|
|
339
|
+
Update names → JSON.parse/stringify → Update name field in 3 files
|
|
340
|
+
↓
|
|
341
|
+
Result → logger.success() → Next steps printed to user
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
### Run Command Data Flow
|
|
345
|
+
|
|
346
|
+
```
|
|
347
|
+
User Input (JSON file path, optional --env flag)
|
|
348
|
+
↓
|
|
349
|
+
Load .env → dotenv.parse() → EnvConfig validation
|
|
350
|
+
↓
|
|
351
|
+
Load JSON file → fs.readFileSync() → JSON.parse() → Zod validation → RunFileConfig
|
|
352
|
+
↓
|
|
353
|
+
Create variables → Map EnvConfig to VariableMap { tenantId, applicationId, token }
|
|
354
|
+
↓
|
|
355
|
+
Interpolate strings → Regex replace {{varName}} → Fully resolved endpoint/headers/body
|
|
356
|
+
↓
|
|
357
|
+
Build full URL → KETRICS_RUNTIME_URL + endpoint → Full HTTP URL
|
|
358
|
+
↓
|
|
359
|
+
HTTP Request → axios() → Method/headers/body from interpolated config → AxiosResponse
|
|
360
|
+
↓
|
|
361
|
+
Display response → JSON.stringify(response.data) → Pretty-printed to console
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
### Configuration Validation Data Flow
|
|
365
|
+
|
|
366
|
+
```
|
|
367
|
+
User Input (optional --config and --env paths)
|
|
368
|
+
↓
|
|
369
|
+
Read ketrics.config.json → fs.readFileSync() → JSON.parse() → Zod parse
|
|
370
|
+
↓
|
|
371
|
+
Collect errors/warnings → Zod error messages + custom checks
|
|
372
|
+
↓
|
|
373
|
+
Read .env → dotenv.config() → Extract KETRICS_* vars → Zod parse
|
|
374
|
+
↓
|
|
375
|
+
Token format check → Regex /^ktd_/ → Warning if doesn't match
|
|
376
|
+
↓
|
|
377
|
+
Return ValidationResult → { valid: boolean, errors: [], warnings: [] }
|
|
378
|
+
↓
|
|
379
|
+
Display results → logger.error() or logger.success()
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
## Error Handling
|
|
383
|
+
|
|
384
|
+
### Error Scenarios and Handling
|
|
385
|
+
|
|
386
|
+
**Configuration Loading Errors**
|
|
387
|
+
- File not found: "Configuration file not found: {path}\nRun 'ketrics init' to create one."
|
|
388
|
+
- Invalid JSON: "Invalid JSON in configuration file: {path}"
|
|
389
|
+
- Zod validation: Field-by-field error messages with paths
|
|
390
|
+
- Recovery: Exit with code 1, display errors before exit
|
|
391
|
+
|
|
392
|
+
**Build Errors**
|
|
393
|
+
- Directory missing: "frontend/ directory not found"
|
|
394
|
+
- Missing node_modules: "Missing node_modules in {name}/. Run 'cd {name} && npm install' first."
|
|
395
|
+
- Build command failure: "{name} build failed. Check the output above for errors."
|
|
396
|
+
- Missing dist: "{name} build did not produce dist/ directory"
|
|
397
|
+
- Recovery: execSync() inherits stdio (shows npm output), thrown Error caught by command handler
|
|
398
|
+
|
|
399
|
+
**API/Network Errors**
|
|
400
|
+
- 401 Unauthorized: "Authentication failed: Invalid or expired deployment token.\nPlease check your KETRICS_TOKEN in the .env file."
|
|
401
|
+
- 403 Forbidden: "Authorization failed: Token does not have access to this application.\nPlease verify KETRICS_TENANT_ID and KETRICS_APPLICATION_ID."
|
|
402
|
+
- 404 Not Found: "Application not found. Please verify KETRICS_APPLICATION_ID."
|
|
403
|
+
- Network unreachable: "Network error: Could not connect to {url}\nPlease check your internet connection and KETRICS_API_URL."
|
|
404
|
+
- S3 upload 400: "Upload failed: Invalid request. The presigned URL may have expired."
|
|
405
|
+
- S3 upload 403: "Upload failed: Access denied. The presigned URL may have expired or been used."
|
|
406
|
+
- S3 upload 413: "Upload failed: File too large. Maximum upload size exceeded."
|
|
407
|
+
- Recovery: Error message logged, process exit(1)
|
|
408
|
+
|
|
409
|
+
**Input Validation Errors**
|
|
410
|
+
- Invalid app name: "App name must start with a letter and contain only letters, numbers, hyphens, and underscores"
|
|
411
|
+
- Missing template: "Template not found: {name}" with list of available templates
|
|
412
|
+
- Directory exists: "Folder '{appName}' already exists."
|
|
413
|
+
- Invalid run JSON: "Invalid run file format:" with detailed Zod path and message
|
|
414
|
+
- Recovery: Error logged, process exit(1)
|
|
420
415
|
|
|
421
|
-
|
|
422
|
-
.env file
|
|
423
|
-
│
|
|
424
|
-
▼
|
|
425
|
-
┌───────────────────┐
|
|
426
|
-
│ Load & Validate │ ── Invalid ──▶ Exit with error
|
|
427
|
-
│ Environment │
|
|
428
|
-
└───────────────────┘
|
|
429
|
-
│
|
|
430
|
-
▼
|
|
431
|
-
┌───────────────────┐
|
|
432
|
-
│ Validate Token │ ── Not ktd_ ──▶ Exit with error
|
|
433
|
-
└───────────────────┘
|
|
434
|
-
│
|
|
435
|
-
▼
|
|
436
|
-
┌───────────────────────────────────────────┐
|
|
437
|
-
│ Build Phase │
|
|
438
|
-
│ ┌─────────────────┐ ┌─────────────────┐ │
|
|
439
|
-
│ │ npm run build │ │ npm run build │ │
|
|
440
|
-
│ │ (frontend) │ │ (backend) │ │
|
|
441
|
-
│ └────────┬────────┘ └────────┬────────┘ │
|
|
442
|
-
│ │ │ │
|
|
443
|
-
│ ▼ ▼ │
|
|
444
|
-
│ frontend/dist/ backend/dist/ │
|
|
445
|
-
└───────────────────────────────────────────┘
|
|
446
|
-
│
|
|
447
|
-
▼
|
|
448
|
-
┌───────────────────┐
|
|
449
|
-
│ Create ZIP │
|
|
450
|
-
│ - frontend/* │
|
|
451
|
-
│ - backend/* │
|
|
452
|
-
│ (level 9 zlib) │
|
|
453
|
-
└───────────────────┘
|
|
454
|
-
│ Buffer
|
|
455
|
-
▼
|
|
456
|
-
┌───────────────────┐ ┌───────────────────┐
|
|
457
|
-
│ Tenant API API │ ──────────────────▶│ DeployResponse │
|
|
458
|
-
│ POST .../deploy │ │ - uploadUrl │
|
|
459
|
-
│ Bearer ktd_... │ │ - deploymentId │
|
|
460
|
-
└───────────────────┘ │ - s3Key │
|
|
461
|
-
└───────────────────┘
|
|
462
|
-
│ uploadUrl
|
|
463
|
-
▼
|
|
464
|
-
┌───────────────────┐
|
|
465
|
-
│ PUT to S3 │
|
|
466
|
-
│ presigned URL │
|
|
467
|
-
│ Content-Type: │
|
|
468
|
-
│ application/zip │
|
|
469
|
-
└───────────────────┘
|
|
470
|
-
│
|
|
471
|
-
▼
|
|
472
|
-
Success box with deploymentId
|
|
473
|
-
```
|
|
474
|
-
|
|
475
|
-
### Run Command Flow
|
|
476
|
-
|
|
477
|
-
```
|
|
478
|
-
JSON config file (e.g., test.greet.json)
|
|
479
|
-
│
|
|
480
|
-
│ {
|
|
481
|
-
│ "endpoint": "/tenants/{{tenantId}}/apps/{{appId}}/functions/greet",
|
|
482
|
-
│ "method": "POST",
|
|
483
|
-
│ "headers": { "Authorization": "Bearer {{token}}" },
|
|
484
|
-
│ "body": { "name": "World" }
|
|
485
|
-
│ }
|
|
486
|
-
│
|
|
487
|
-
▼
|
|
488
|
-
┌───────────────────┐
|
|
489
|
-
│ Load .env │
|
|
490
|
-
│ (KETRICS_AUTH_ │
|
|
491
|
-
│ TOKEN required) │
|
|
492
|
-
└───────────────────┘
|
|
493
|
-
│
|
|
494
|
-
▼
|
|
495
|
-
┌───────────────────┐
|
|
496
|
-
│ Parse & Validate │ ── Zod runFileSchema
|
|
497
|
-
│ JSON File │
|
|
498
|
-
└───────────────────┘
|
|
499
|
-
│
|
|
500
|
-
▼
|
|
501
|
-
┌───────────────────┐
|
|
502
|
-
│ Interpolate Vars │ ── Replace {{tenantId}}, {{applicationId}}, {{token}}
|
|
503
|
-
└───────────────────┘
|
|
504
|
-
│
|
|
505
|
-
▼
|
|
506
|
-
┌───────────────────┐
|
|
507
|
-
│ Execute Request │ ── axios({ method, url, headers, data })
|
|
508
|
-
│ KETRICS_RUNTIME_ │
|
|
509
|
-
│ URL + endpoint │
|
|
510
|
-
└───────────────────┘
|
|
511
|
-
│
|
|
512
|
-
▼
|
|
513
|
-
Formatted response (status + JSON body)
|
|
514
|
-
```
|
|
416
|
+
### Retry Logic
|
|
515
417
|
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
| Scenario | Detection | User Message |
|
|
523
|
-
| ---------------------- | -------------------------------- | ----------------------------------------------------------------------------------------------- |
|
|
524
|
-
| Missing .env file | `fs.existsSync()` check | "Environment file not found: {path}" |
|
|
525
|
-
| Invalid JSON in config | JSON.parse throws | "Invalid JSON in configuration file: {path}" |
|
|
526
|
-
| Zod validation failure | `safeParse().success === false` | "Invalid configuration:\n - {field}: {message}" |
|
|
527
|
-
| Invalid token format | String prefix check | "Invalid token format. Token should start with 'ktd\_'" |
|
|
528
|
-
| Missing node_modules | Directory check | "Missing node_modules in {dir}/. Run 'cd {dir} && npm install' first." |
|
|
529
|
-
| Build failure | execSync throws | "{name} build failed. Check the output above for errors." |
|
|
530
|
-
| No dist directory | Post-build directory check | "{name} build did not produce dist/ directory" |
|
|
531
|
-
| API 401 | HTTP status check | "Authentication failed: Invalid or expired deployment token." |
|
|
532
|
-
| API 403 | HTTP status check | "Authorization failed: Token does not have access to this application." |
|
|
533
|
-
| API 404 | HTTP status check | "Application not found. Please verify KETRICS_APPLICATION_ID." |
|
|
534
|
-
| Network error | axios.isAxiosError + no response | "Network error: Could not connect to {url}" |
|
|
535
|
-
| S3 upload 403 | HTTP status check | "Upload failed: Access denied. The presigned URL may have expired or been used." |
|
|
536
|
-
| S3 upload 413 | HTTP status check | "Upload failed: File too large. Maximum upload size exceeded." |
|
|
537
|
-
| Upload timeout | axios timeout | "Upload failed: Network error. Please check your internet connection." |
|
|
538
|
-
| Folder already exists | `fs.existsSync()` | "Folder '{name}' already exists." |
|
|
539
|
-
| Invalid app name | Regex test | "App name must start with a letter and contain only letters, numbers, hyphens, and underscores" |
|
|
418
|
+
- **Explicit Retries**: None implemented—all operations are single-attempt
|
|
419
|
+
- **Presigned URL Expiration**: 15 minutes (expiresInSeconds from API response)
|
|
420
|
+
- **Timeout Handling**:
|
|
421
|
+
- API calls: 30 second timeout
|
|
422
|
+
- S3 uploads: 300 second timeout (5 minutes)
|
|
423
|
+
- User can re-run command if timeout occurs
|
|
540
424
|
|
|
541
|
-
###
|
|
425
|
+
### Fallback Mechanisms
|
|
542
426
|
|
|
543
|
-
|
|
427
|
+
- **Template Selection**: If multiple templates exist, interactive selection via inquirer; if one template exists, auto-select; if none exist, error with instructions
|
|
428
|
+
- **Build Validation**: Checks for node_modules and package.json before running npm build
|
|
429
|
+
- **Token Format**: Validates token format (`ktd_` prefix) before API call, providing early feedback
|
|
430
|
+
- **Variable Interpolation**: Unknown variables in run JSON remain as-is with warning logged
|
|
544
431
|
|
|
545
432
|
### Logging Approach
|
|
546
433
|
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
logger.box(title, [...])// Green success box with details
|
|
557
|
-
```
|
|
434
|
+
**Logger Levels** (not severity-based, visual categorization):
|
|
435
|
+
- `info()`: Blue "ℹ" icon + message (informational)
|
|
436
|
+
- `success()`: Green "✔" icon + message (operation succeeded)
|
|
437
|
+
- `warn()`: Yellow "⚠" icon + message (non-blocking issues)
|
|
438
|
+
- `error()`: Red "✖" icon + message (operation failed)
|
|
439
|
+
- `log()`: Plain text (neutral output)
|
|
440
|
+
- `header()`: Bold text with newlines (section markers)
|
|
441
|
+
- `keyValue()`: Gray key + value (structured data)
|
|
442
|
+
- `box()`: Green checkmark box (success summary)
|
|
558
443
|
|
|
559
|
-
|
|
444
|
+
**Log Points**:
|
|
445
|
+
1. Command start: `logger.header()` with command name
|
|
446
|
+
2. Major operation start: `withSpinner()` text
|
|
447
|
+
3. Operation completion: `spinner.succeed()` text
|
|
448
|
+
4. Data summaries: `logger.keyValue()` for important values
|
|
449
|
+
5. Errors: `logger.error()` before exit or throw
|
|
450
|
+
6. Success: `logger.box()` or `logger.success()` at end
|
|
560
451
|
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
452
|
+
**Example Deploy Logging**:
|
|
453
|
+
```
|
|
454
|
+
Ketrics CLI v1.0.0 [header]
|
|
455
|
+
ℹ Loading environment... [spinner start]
|
|
456
|
+
✔ Loaded environment [spinner succeed]
|
|
457
|
+
Building frontend... [info]
|
|
458
|
+
Building backend... [info]
|
|
459
|
+
✔ Build completed [success]
|
|
460
|
+
Frontend dist: ... [keyValue]
|
|
567
461
|
```
|
|
568
462
|
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
---
|
|
572
|
-
|
|
573
|
-
## 6. Usage
|
|
463
|
+
## Usage
|
|
574
464
|
|
|
575
|
-
### Installation
|
|
465
|
+
### Installation and Setup
|
|
576
466
|
|
|
577
467
|
```bash
|
|
578
|
-
#
|
|
468
|
+
# Install globally
|
|
579
469
|
npm install -g @ketrics/ketrics-cli
|
|
580
470
|
|
|
581
|
-
# Or
|
|
582
|
-
|
|
471
|
+
# Or use as dev dependency
|
|
472
|
+
npm install --save-dev @ketrics/ketrics-cli
|
|
583
473
|
|
|
584
|
-
#
|
|
585
|
-
|
|
586
|
-
npm install
|
|
587
|
-
npm run build
|
|
588
|
-
npm link
|
|
474
|
+
# Verify installation
|
|
475
|
+
ketrics --version
|
|
589
476
|
```
|
|
590
477
|
|
|
591
|
-
### Commands
|
|
478
|
+
### Running Commands
|
|
592
479
|
|
|
593
|
-
#### Create New Application
|
|
480
|
+
#### Create a New Application
|
|
594
481
|
|
|
595
482
|
```bash
|
|
596
483
|
# Interactive template selection
|
|
597
484
|
ketrics create my-app
|
|
598
485
|
|
|
599
|
-
#
|
|
600
|
-
ketrics create my-app --template
|
|
486
|
+
# Specify template directly
|
|
487
|
+
ketrics create my-app --template HelloWorld
|
|
601
488
|
```
|
|
602
489
|
|
|
603
|
-
|
|
490
|
+
**Output**:
|
|
491
|
+
- New directory `my-app/` with template structure
|
|
492
|
+
- Console instructions for next steps
|
|
493
|
+
- Pre-configured `ketrics.config.json` and package.json files
|
|
494
|
+
|
|
495
|
+
**Prerequisites**: None (discovers templates from bundled templates/)
|
|
496
|
+
|
|
497
|
+
#### Build Application
|
|
604
498
|
|
|
605
499
|
```bash
|
|
500
|
+
cd my-app
|
|
606
501
|
ketrics build
|
|
607
502
|
```
|
|
608
503
|
|
|
609
|
-
|
|
504
|
+
**Output**:
|
|
505
|
+
- Compiled `frontend/dist/` directory
|
|
506
|
+
- Compiled `backend/dist/` directory
|
|
507
|
+
- Console summary with paths
|
|
508
|
+
|
|
509
|
+
**Prerequisites**:
|
|
510
|
+
- Current directory contains `frontend/` and `backend/` subdirectories
|
|
511
|
+
- Both directories have `node_modules/` installed
|
|
512
|
+
- Both directories have `package.json` with `build` script
|
|
513
|
+
|
|
514
|
+
#### Deploy Application
|
|
610
515
|
|
|
611
516
|
```bash
|
|
612
517
|
# Standard deployment
|
|
613
518
|
ketrics deploy
|
|
614
519
|
|
|
615
|
-
#
|
|
616
|
-
ketrics deploy --env
|
|
520
|
+
# Custom .env path
|
|
521
|
+
ketrics deploy --env ./config/.env.production
|
|
617
522
|
|
|
618
|
-
#
|
|
523
|
+
# Dry run (see what would deploy without uploading)
|
|
619
524
|
ketrics deploy --dry-run
|
|
620
525
|
```
|
|
621
526
|
|
|
527
|
+
**Output**:
|
|
528
|
+
- Deployment ID
|
|
529
|
+
- File count and total size
|
|
530
|
+
- Processing confirmation
|
|
531
|
+
|
|
532
|
+
**Prerequisites**:
|
|
533
|
+
- `.env` file with KETRICS_TOKEN, KETRICS_API_URL, KETRICS_TENANT_ID, KETRICS_APPLICATION_ID
|
|
534
|
+
- Built `frontend/dist/` and `backend/dist/` directories
|
|
535
|
+
- Valid deployment token (starts with `ktd_`)
|
|
536
|
+
|
|
622
537
|
#### Validate Configuration
|
|
623
538
|
|
|
624
539
|
```bash
|
|
625
|
-
# Validate
|
|
540
|
+
# Validate with defaults
|
|
626
541
|
ketrics validate
|
|
627
542
|
|
|
628
|
-
#
|
|
629
|
-
ketrics validate --config ./
|
|
543
|
+
# Custom paths
|
|
544
|
+
ketrics validate --config ./config/ketrics.config.json --env ./.env.staging
|
|
630
545
|
```
|
|
631
546
|
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
ketrics run tests/test.greet.json
|
|
637
|
-
|
|
638
|
-
# With custom .env and verbose output
|
|
639
|
-
ketrics run tests/test.echo.json --env .env.local --verbose
|
|
640
|
-
```
|
|
547
|
+
**Output**:
|
|
548
|
+
- List of errors (if any)
|
|
549
|
+
- List of warnings (if any)
|
|
550
|
+
- Success/failure status
|
|
641
551
|
|
|
642
|
-
|
|
552
|
+
**Prerequisites**: None (creates validation report even if files don't exist)
|
|
643
553
|
|
|
644
|
-
|
|
554
|
+
#### Execute API Requests
|
|
645
555
|
|
|
646
|
-
```
|
|
556
|
+
```bash
|
|
557
|
+
# Create request file: request.json
|
|
647
558
|
{
|
|
648
|
-
"endpoint": "/
|
|
649
|
-
"method": "
|
|
559
|
+
"endpoint": "/users/{{tenantId}}/profile",
|
|
560
|
+
"method": "GET",
|
|
650
561
|
"headers": {
|
|
651
|
-
"Authorization": "Bearer {{token}}"
|
|
652
|
-
"Content-Type": "application/json"
|
|
653
|
-
},
|
|
654
|
-
"body": {
|
|
655
|
-
"name": "World"
|
|
562
|
+
"Authorization": "Bearer {{token}}"
|
|
656
563
|
}
|
|
657
564
|
}
|
|
565
|
+
|
|
566
|
+
# Execute request
|
|
567
|
+
ketrics run request.json
|
|
568
|
+
|
|
569
|
+
# Verbose output
|
|
570
|
+
ketrics run request.json --verbose
|
|
571
|
+
|
|
572
|
+
# Custom .env
|
|
573
|
+
ketrics run request.json --env ./.env.dev
|
|
658
574
|
```
|
|
659
575
|
|
|
660
|
-
|
|
576
|
+
**Output**:
|
|
577
|
+
- Formatted HTTP request (method, URL, headers, body)
|
|
578
|
+
- Formatted HTTP response (status, body)
|
|
579
|
+
- Duration in seconds
|
|
580
|
+
|
|
581
|
+
**Prerequisites**:
|
|
582
|
+
- `.env` file with KETRICS_AUTH_TOKEN and KETRICS_RUNTIME_URL
|
|
583
|
+
- Valid JSON request file
|
|
661
584
|
|
|
585
|
+
### Example Invocations
|
|
586
|
+
|
|
587
|
+
**Full Deployment Workflow**:
|
|
662
588
|
```bash
|
|
663
|
-
#
|
|
664
|
-
|
|
589
|
+
# Create new project
|
|
590
|
+
ketrics create my-todo-app --template HelloWorld
|
|
665
591
|
|
|
666
|
-
#
|
|
667
|
-
|
|
668
|
-
npm run dev -- deploy --dry-run
|
|
592
|
+
# Navigate to project
|
|
593
|
+
cd my-todo-app
|
|
669
594
|
|
|
670
|
-
#
|
|
671
|
-
npm
|
|
672
|
-
|
|
595
|
+
# Install dependencies
|
|
596
|
+
cd frontend && npm install
|
|
597
|
+
cd ../backend && npm install
|
|
598
|
+
cd ..
|
|
673
599
|
|
|
674
|
-
|
|
600
|
+
# Copy .env from template
|
|
601
|
+
cp .env.example .env
|
|
602
|
+
# Edit .env with your credentials
|
|
675
603
|
|
|
676
|
-
|
|
604
|
+
# Validate configuration
|
|
605
|
+
ketrics validate
|
|
677
606
|
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
- `ketrics create test-app`
|
|
681
|
-
- `cd test-app/frontend && npm install && cd ../backend && npm install`
|
|
682
|
-
- Configure `.env` with real credentials
|
|
683
|
-
- `ketrics deploy --dry-run` to verify packaging
|
|
684
|
-
- `ketrics deploy` to test full flow
|
|
685
|
-
3. **Runtime testing**: Use `ketrics run tests/test.*.json` against deployed application
|
|
607
|
+
# Build application
|
|
608
|
+
ketrics build
|
|
686
609
|
|
|
687
|
-
|
|
610
|
+
# Deploy to Ketrics
|
|
611
|
+
ketrics deploy
|
|
612
|
+
```
|
|
688
613
|
|
|
614
|
+
**Testing API Endpoints**:
|
|
689
615
|
```bash
|
|
690
|
-
# Create
|
|
691
|
-
|
|
616
|
+
# Create .env with runtime credentials
|
|
617
|
+
cat > .env.test << EOF
|
|
618
|
+
KETRICS_TENANT_ID=12345678-1234-1234-1234-123456789012
|
|
619
|
+
KETRICS_APPLICATION_ID=87654321-4321-4321-4321-210987654321
|
|
620
|
+
KETRICS_AUTH_TOKEN=your_runtime_token_here
|
|
621
|
+
KETRICS_RUNTIME_URL=https://api.runtime.ketrics.io
|
|
622
|
+
EOF
|
|
623
|
+
|
|
624
|
+
# Create request file
|
|
625
|
+
cat > api-test.json << EOF
|
|
626
|
+
{
|
|
627
|
+
"endpoint": "/health",
|
|
628
|
+
"method": "GET",
|
|
629
|
+
"headers": {
|
|
630
|
+
"Authorization": "Bearer {{token}}"
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
EOF
|
|
692
634
|
|
|
693
|
-
|
|
635
|
+
# Execute
|
|
636
|
+
ketrics run api-test.json --env .env.test
|
|
637
|
+
```
|
|
694
638
|
|
|
695
|
-
|
|
696
|
-
hello-world/ketrics.config.json
|
|
697
|
-
hello-world/frontend/package.json
|
|
698
|
-
hello-world/backend/package.json
|
|
699
|
-
...
|
|
639
|
+
### Testing Approach
|
|
700
640
|
|
|
701
|
-
|
|
641
|
+
**Unit Testing** (not included in code):
|
|
642
|
+
- Would test individual service functions: `loadEnvConfig()`, `buildAll()`, `collectFiles()`, etc.
|
|
643
|
+
- Mock file system, axios, child_process
|
|
644
|
+
- Verify schema validation with valid/invalid inputs
|
|
645
|
+
- Test error handling paths
|
|
646
|
+
|
|
647
|
+
**Integration Testing** (not included in code):
|
|
648
|
+
- Test complete command workflows
|
|
649
|
+
- Use temporary directories and files
|
|
650
|
+
- Mock Ketrics API responses
|
|
651
|
+
- Verify file structure creation and modification
|
|
652
|
+
|
|
653
|
+
**Manual Testing** (recommended):
|
|
654
|
+
1. Create test project with `ketrics create test-app`
|
|
655
|
+
2. Modify `.env` with test credentials
|
|
656
|
+
3. Run `ketrics validate` to verify setup
|
|
657
|
+
4. Run `ketrics build` to verify npm scripts exist
|
|
658
|
+
5. Run `ketrics deploy --dry-run` to verify packaging
|
|
659
|
+
6. Run `ketrics run` with test request to verify runtime access
|
|
660
|
+
7. Full `ketrics deploy` to staging environment
|
|
661
|
+
|
|
662
|
+
**Testing Checklist**:
|
|
663
|
+
- Create command with interactive and flag-based template selection
|
|
664
|
+
- Build command with missing node_modules, missing dist directories
|
|
665
|
+
- Deploy command with invalid token format, network errors, S3 failures
|
|
666
|
+
- Validate command with missing files, invalid JSON, schema violations
|
|
667
|
+
- Run command with missing variables, malformed JSON, API errors
|
|
668
|
+
- Edge cases: empty directories, very large files, special characters in names
|
|
669
|
+
|
|
670
|
+
## Advanced Topics
|
|
671
|
+
|
|
672
|
+
### Custom Configuration Patterns
|
|
673
|
+
|
|
674
|
+
The `include`/`exclude` patterns in `ketrics.config.json` use glob syntax:
|
|
702
675
|
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
676
|
+
```json
|
|
677
|
+
{
|
|
678
|
+
"include": [
|
|
679
|
+
"frontend/dist/**/*",
|
|
680
|
+
"backend/dist/**/*"
|
|
681
|
+
],
|
|
682
|
+
"exclude": [
|
|
683
|
+
"**/*.map",
|
|
684
|
+
"**/node_modules/**",
|
|
685
|
+
"**/.git/**"
|
|
686
|
+
]
|
|
687
|
+
}
|
|
688
|
+
```
|
|
709
689
|
|
|
710
|
-
|
|
711
|
-
$ cd hello-world
|
|
712
|
-
$ cd frontend && npm install && cd ../backend && npm install
|
|
690
|
+
### Programmatic Usage
|
|
713
691
|
|
|
714
|
-
|
|
715
|
-
$ cp .env.example .env
|
|
716
|
-
$ vim .env # Add your KETRICS_TOKEN, etc.
|
|
692
|
+
The CLI exports services for use in other Node.js applications:
|
|
717
693
|
|
|
718
|
-
|
|
719
|
-
|
|
694
|
+
```typescript
|
|
695
|
+
import {
|
|
696
|
+
loadEnvConfig,
|
|
697
|
+
buildAll,
|
|
698
|
+
createDeploymentZipBundle,
|
|
699
|
+
uploadToS3,
|
|
700
|
+
initiateDeploy
|
|
701
|
+
} from '@ketrics/ketrics-cli';
|
|
702
|
+
|
|
703
|
+
// Load config
|
|
704
|
+
const config = loadEnvConfig('/path/to/.env');
|
|
705
|
+
|
|
706
|
+
// Build application
|
|
707
|
+
const buildResult = buildAll(process.cwd());
|
|
708
|
+
|
|
709
|
+
// Create ZIP
|
|
710
|
+
const zip = await createDeploymentZipBundle(
|
|
711
|
+
buildResult.frontendDistPath,
|
|
712
|
+
buildResult.backendDistPath
|
|
713
|
+
);
|
|
720
714
|
|
|
721
|
-
|
|
715
|
+
// Upload
|
|
716
|
+
await uploadToS3(presignedUrl, zip.buffer);
|
|
717
|
+
```
|
|
718
|
+
|
|
719
|
+
### Environment-Specific Deployments
|
|
722
720
|
|
|
723
|
-
|
|
724
|
-
✔ Validated deployment token
|
|
721
|
+
Use different `.env` files for different environments:
|
|
725
722
|
|
|
726
|
-
|
|
723
|
+
```bash
|
|
724
|
+
# Staging
|
|
725
|
+
ketrics deploy --env .env.staging
|
|
726
|
+
|
|
727
|
+
# Production
|
|
728
|
+
ketrics deploy --env .env.production
|
|
729
|
+
```
|
|
727
730
|
|
|
728
|
-
|
|
729
|
-
> vite build
|
|
730
|
-
...
|
|
731
|
+
### Debugging
|
|
731
732
|
|
|
732
|
-
|
|
733
|
-
✔ Created deployment ZIP archive
|
|
734
|
-
✔ ZIP archive: 45.2 KB from 6 files
|
|
735
|
-
✔ Initiated deployment
|
|
736
|
-
✔ Uploaded to S3
|
|
733
|
+
Enable verbose output where available:
|
|
737
734
|
|
|
738
|
-
|
|
735
|
+
```bash
|
|
736
|
+
# Run command with verbose flag
|
|
737
|
+
ketrics run request.json --verbose
|
|
739
738
|
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
Size: 45.2 KB
|
|
743
|
-
Duration: 4.1s
|
|
739
|
+
# Build process inherits stdio (shows npm output)
|
|
740
|
+
ketrics build # Shows all npm build output
|
|
744
741
|
|
|
745
|
-
|
|
742
|
+
# API client logs URL before request
|
|
743
|
+
# (Search for "console.log" in api-client.ts for debug points)
|
|
746
744
|
```
|
|
745
|
+
|
|
746
|
+
## Version Information
|
|
747
|
+
|
|
748
|
+
- **CLI Version**: 0.2.3 (auto-generated in `src/version.ts`)
|
|
749
|
+
- **Node.js Requirement**: 24.0.0 or later
|
|
750
|
+
- **TypeScript**: 5.3.3
|
|
751
|
+
- **Last Updated**: 2024-2025
|
|
752
|
+
|
|
753
|
+
## Contributing
|
|
754
|
+
|
|
755
|
+
When modifying the CLI:
|
|
756
|
+
1. Follow TypeScript strict mode (tsconfig.json)
|
|
757
|
+
2. Export types and services from `src/index.ts`
|
|
758
|
+
3. Add Zod schemas for new configuration options
|
|
759
|
+
4. Use logger utility instead of console.log
|
|
760
|
+
5. Wrap async operations with withSpinner for UX
|
|
761
|
+
6. Run `npm run build` before testing (generates version.ts)
|
|
762
|
+
7. Test all command paths, especially error scenarios
|