@ketrics/ketrics-cli 0.1.0 → 0.2.1

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,326 +1,746 @@
1
1
  # Ketrics CLI
2
2
 
3
- CLI tool for deploying applications to the Ketrics platform.
3
+ Command-line interface for scaffolding, building, and deploying applications to the Ketrics platform.
4
4
 
5
- ## Installation
5
+ ## 1. Overview
6
6
 
7
- ```bash
8
- # Install globally
9
- npm install -g ketrics-cli
7
+ ### Purpose
10
8
 
11
- # Or use npx
12
- npx ketrics-cli deploy
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.
13
10
 
14
- # Or link locally for development
15
- cd ketrics-cli
16
- npm install
17
- npm run build
18
- npm link
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
+ └──────────────┘
19
41
  ```
20
42
 
21
- ## Quick Start
43
+ The CLI sits at the beginning of the deployment pipeline:
22
44
 
23
- 1. **Create a new application from template:**
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
24
49
 
25
- ```bash
26
- ketrics create my-app
27
- ```
50
+ ### Key Responsibilities
28
51
 
29
- This will:
30
- - Create a new folder `my-app/`
31
- - Let you choose a template interactively
32
- - Copy template files to the folder
33
- - Update app name in configuration files
52
+ - **Project scaffolding**: Generate new applications from bundled templates
53
+ - **Configuration validation**: Validate `ketrics.config.json` and `.env` files using Zod schemas
54
+ - **Build orchestration**: Execute `npm run build` for both frontend and backend
55
+ - **Deployment packaging**: Create ZIP archives with frontend/backend in a flat structure
56
+ - **API communication**: Authenticate with Tenant API and obtain presigned upload URLs
57
+ - **S3 upload**: Push deployment bundles to the platform
58
+ - **Runtime testing**: Execute API requests against deployed applications via `ketrics run`
34
59
 
35
- 2. **Install dependencies:**
60
+ ### Boundaries
36
61
 
37
- ```bash
38
- cd my-app
39
- cd frontend && npm install
40
- cd ../backend && npm install
41
- ```
62
+ The CLI does **not**:
42
63
 
43
- 3. **Configure credentials** (copy `.env.example` to `.env`):
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)
44
68
 
45
- ```bash
46
- KETRICS_TOKEN=ktd_your-token-id_your-secret-key
47
- KETRICS_API_URL=https://api.ketrics.cl/api/v1
48
- KETRICS_TENANT_ID=your-tenant-uuid
49
- KETRICS_APPLICATION_ID=your-application-uuid
50
- ```
69
+ ---
51
70
 
52
- 4. **Deploy:**
53
- ```bash
54
- ketrics deploy
55
- ```
71
+ ## 2. Business Logic
56
72
 
57
- The CLI will:
58
- - Build frontend (npm run build)
59
- - Build backend (npm run build)
60
- - Create ZIP with both builds
61
- - Upload to Ketrics platform
73
+ ### Problem Statement
62
74
 
63
- ## Commands
75
+ Developers building Ketrics applications need a consistent, reliable way to:
64
76
 
65
- ### `ketrics create <app-name>`
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
66
81
 
67
- Create a new Ketrics application from a template.
82
+ ### Core Workflows
83
+
84
+ #### Scaffold Workflow (`ketrics create`)
68
85
 
69
- ```bash
70
- ketrics create my-app # Interactive template selection
71
- ketrics create my-app --template <name> # Use specific template
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
72
93
  ```
73
94
 
74
- **What it does:**
75
- 1. Creates a folder with the provided app name (fails if folder exists)
76
- 2. Prompts for template selection (or uses `--template` flag)
77
- 3. Copies template files to the new folder
78
- 4. Updates app name in:
79
- - `ketrics.config.json`
80
- - `frontend/package.json`
81
- - `backend/package.json`
95
+ #### Build Workflow (`ketrics build`)
82
96
 
83
- ### `ketrics build`
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
+ ```
84
104
 
85
- Build frontend and backend without deploying.
105
+ #### Deploy Workflow (`ketrics deploy`)
86
106
 
87
- ```bash
88
- ketrics build
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
89
118
  ```
90
119
 
91
- **What it does:**
92
- 1. Runs `npm run build` in `frontend/`
93
- 2. Runs `npm run build` in `backend/`
94
- 3. Outputs the location of built files
120
+ #### Validate Workflow (`ketrics validate`)
95
121
 
96
- ### `ketrics deploy`
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
+ ```
97
129
 
98
- Build and deploy frontend/backend to Ketrics.
130
+ #### Run Workflow (`ketrics run <json-file>`)
99
131
 
100
- ```bash
101
- ketrics deploy # Build and deploy
102
- ketrics deploy --env <path> # Use specific .env file
103
- ketrics deploy --dry-run # Build and show what would be deployed
104
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
176
+
177
+ - **Destination folder exists**: `ketrics create` fails early with clear error
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
183
+
184
+ ---
185
+
186
+ ## 3. Technical Details
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
105
205
 
106
- **What it does:**
107
- 1. Validates `.env` configuration
108
- 2. Builds `frontend/` (runs `npm run build`)
109
- 3. Builds `backend/` (runs `npm run build`)
110
- 4. Creates ZIP with flat structure:
111
- - `frontend/` - contents of `frontend/dist/`
112
- - `backend/` - contents of `backend/dist/`
113
- 5. Uploads to S3 via presigned URL
206
+ ```
207
+ ketrics-cli/
208
+ ├── bin/
209
+ │ └── ketrics.ts # CLI entry point (shebang executable)
210
+ ├── src/
211
+ ├── cli.ts # Commander program setup, command registration
212
+ ├── index.ts # Programmatic exports for library usage
213
+ │ ├── commands/
214
+ │ │ ├── create.ts # ketrics create - project scaffolding
215
+ │ │ ├── build.ts # ketrics build - compile without deploy
216
+ │ │ ├── deploy.ts # ketrics deploy - build + package + upload
217
+ │ │ ├── validate.ts # ketrics validate - config validation
218
+ │ │ └── run.ts # ketrics run - execute API requests
219
+ │ ├── services/
220
+ │ │ ├── api-client.ts # HTTP client for Tenant API API
221
+ │ │ ├── build-service.ts # npm build execution and validation
222
+ │ │ ├── config-service.ts # Load/validate ketrics.config.json and .env
223
+ │ │ ├── template-service.ts # Template discovery, copying, name updates
224
+ │ │ ├── upload-service.ts # S3 presigned URL upload
225
+ │ │ └── zip-service.ts # ZIP archive creation from dist directories
226
+ │ ├── types/
227
+ │ │ └── index.ts # Zod schemas and TypeScript interfaces
228
+ │ └── utils/
229
+ │ ├── logger.ts # Colored console output (chalk wrapper)
230
+ │ └── spinner.ts # Loading spinner wrapper (ora)
231
+ ├── templates/
232
+ │ └── ketrics-app-v1/ # Bundled project template
233
+ │ ├── ketrics.config.json
234
+ │ ├── frontend/ # React + Vite starter
235
+ │ ├── backend/ # TypeScript handlers starter
236
+ │ └── tests/ # Sample run files for ketrics run
237
+ ├── package.json
238
+ └── tsconfig.json
239
+ ```
114
240
 
115
- ### `ketrics validate`
241
+ ### Key Functions and Classes
116
242
 
117
- Validate configuration and `.env` files.
243
+ #### `src/cli.ts`
118
244
 
119
- ```bash
120
- ketrics validate # Validate default files
121
- ketrics validate --env <path> # Validate specific .env
245
+ ```typescript
246
+ export function createCLI(): Command;
122
247
  ```
123
248
 
124
- ### `ketrics --version`
249
+ Creates the Commander program with all commands registered. Each command is defined with options, descriptions, and action handlers.
125
250
 
126
- Show CLI version.
251
+ #### `src/services/config-service.ts`
127
252
 
128
- ### `ketrics --help`
253
+ ```typescript
254
+ export function loadKetricsConfig(configPath?: string): KetricsConfig;
255
+ ```
129
256
 
130
- Show help information.
257
+ Loads and validates `ketrics.config.json` against the Zod schema. Throws descriptive errors for missing files or validation failures.
131
258
 
132
- ## Project Structure
259
+ ```typescript
260
+ export function loadEnvConfig(envPath?: string): EnvConfig;
261
+ ```
133
262
 
134
- After running `ketrics create my-app`, your project will have:
263
+ Loads `.env` file using dotenv, extracts `KETRICS_*` variables, and validates against schema.
135
264
 
265
+ ```typescript
266
+ export function validateConfig(configPath?: string, envPath?: string): ValidationResult;
136
267
  ```
137
- my-app/
138
- ├── .env.example # Environment variables template
139
- ├── .gitignore # Git ignore file
140
- ├── ketrics.config.json # Application configuration
141
- ├── README.md # Documentation
142
- ├── frontend/ # React + TypeScript + Vite
143
- │ ├── src/
144
- │ ├── package.json
145
- │ └── vite.config.ts
146
- └── backend/ # TypeScript handlers
147
- ├── src/
148
- ├── package.json
149
- └── tsconfig.json
268
+
269
+ Non-throwing validation that returns `{ valid: boolean, errors: string[], warnings: string[] }`.
270
+
271
+ #### `src/services/build-service.ts`
272
+
273
+ ```typescript
274
+ export function buildAll(projectDir: string): BuildResult;
150
275
  ```
151
276
 
152
- ## Configuration
277
+ Orchestrates building both frontend and backend. Returns paths to both `dist/` directories. Executes `npm run build` via `child_process.execSync` with `stdio: 'inherit'` to show build output.
153
278
 
154
- ### `ketrics.config.json`
279
+ ```typescript
280
+ export function validateBuildDirectory(dir: string, name: string): BuildValidation;
281
+ ```
282
+
283
+ Checks that a directory exists, has `node_modules`, and has `package.json`.
155
284
 
156
- | Field | Type | Required | Description |
157
- | ------------- | -------- | -------- | ---------------------------------------- |
158
- | `name` | string | Yes | Application name |
159
- | `version` | string | Yes | Semver version (e.g., "1.0.0") |
160
- | `description` | string | No | Application description |
161
- | `runtime` | string | Yes | Runtime: "nodejs18", "nodejs20", "static"|
162
- | `actions` | string[] | Yes | List of exported backend actions |
163
- | `entry` | string | Yes | Backend entry point file |
164
- | `include` | string[] | Yes | Glob patterns for files to include |
165
- | `exclude` | string[] | No | Glob patterns for files to exclude |
285
+ #### `src/services/zip-service.ts`
166
286
 
167
- ### Environment Variables
287
+ ```typescript
288
+ export async function createDeploymentZipBundle(
289
+ frontendDistPath: string,
290
+ backendDistPath: string,
291
+ ): Promise<{ buffer: Buffer; files: FileInfo[]; totalSourceSize: number; zipSize: number }>;
292
+ ```
168
293
 
169
- | Variable | Required | Description |
170
- | ------------------------ | -------- | -------------------------------- |
171
- | `KETRICS_TOKEN` | Yes | Deployment token from dashboard |
172
- | `KETRICS_API_URL` | Yes | Ketrics API URL |
173
- | `KETRICS_TENANT_ID` | Yes | Your tenant UUID |
174
- | `KETRICS_APPLICATION_ID` | Yes | Application UUID |
294
+ Creates a ZIP buffer from frontend and backend dist directories. Uses archiver with `zlib: { level: 9 }` for maximum compression. Files are organized under `frontend/` and `backend/` prefixes.
175
295
 
176
- ## Deployment Flow
296
+ #### `src/services/api-client.ts`
177
297
 
178
- 1. Load `.env` file and validate Ketrics variables
179
- 2. Build frontend using `npm run build`
180
- 3. Build backend using `npm run build`
181
- 4. Create ZIP with `frontend/` and `backend/` folders
182
- 5. Request presigned URL from Ketrics API
183
- 6. Upload ZIP to S3 via presigned URL
184
- 7. Display deployment success with deployment ID
298
+ ```typescript
299
+ export async function initiateDeploy(envConfig: EnvConfig): Promise<DeployResponse>;
300
+ ```
185
301
 
186
- ## Example Output
302
+ Calls `POST /tenants/{tenantId}/applications/{appId}/deploy` with Bearer token authentication. Returns presigned URL, deploymentId, and S3 key. Handles 401/403/404 with user-friendly error messages.
187
303
 
188
- ### Create Command
304
+ #### `src/services/upload-service.ts`
189
305
 
306
+ ```typescript
307
+ export async function uploadToS3(presignedUrl: string, zipBuffer: Buffer): Promise<void>;
190
308
  ```
191
- $ ketrics create my-app
192
309
 
193
- Available Templates
310
+ Uploads ZIP buffer to S3 via presigned URL using PUT with `Content-Type: application/zip`. 5-minute timeout for large uploads.
194
311
 
195
- 1. ketrics-app-v1
196
- My Ketrics application
312
+ #### `src/services/template-service.ts`
197
313
 
198
- Select a template (enter number): 1
314
+ ```typescript
315
+ export function getAvailableTemplates(): TemplateInfo[];
316
+ ```
199
317
 
200
- Creating 'my-app' with template: ketrics-app-v1
318
+ Scans the `templates/` directory for subdirectories containing `ketrics.config.json`.
201
319
 
202
- Files to create:
203
- my-app/.env.example
204
- my-app/.gitignore
205
- my-app/README.md
206
- my-app/ketrics.config.json
207
- my-app/backend/package.json
208
- my-app/backend/src/index.ts
209
- ...
320
+ ```typescript
321
+ export function copyTemplate(template: TemplateInfo, destDir: string): void;
322
+ ```
210
323
 
211
- Created 'my-app' successfully!
324
+ Recursively copies template files to destination directory.
212
325
 
213
- Next steps:
214
- 1. cd my-app
215
- 2. cd frontend && npm install
216
- 3. cd ../backend && npm install
217
- 4. Copy .env.example to .env and add your credentials
218
- 5. Run 'ketrics deploy' to deploy your application
326
+ ```typescript
327
+ export function updateAppName(projectDir: string, appName: string): void;
219
328
  ```
220
329
 
221
- ### Build Command
330
+ Updates the `name` field in `ketrics.config.json`, `frontend/package.json`, and `backend/package.json`.
331
+
332
+ ### Configuration Options
222
333
 
334
+ #### `ketrics.config.json` Schema
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
+ });
223
347
  ```
224
- $ ketrics build
225
348
 
226
- Ketrics CLI v1.0.0 - Build
349
+ #### Environment Variables
227
350
 
228
- Building frontend and backend...
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 |
229
359
 
230
- > frontend build output...
231
- > backend build output...
360
+ ### External Integrations
232
361
 
233
- Build completed successfully!
362
+ 1. **Tenant API API**:
363
+ - Endpoint: `POST /tenants/{tenantId}/applications/{applicationId}/deploy`
364
+ - Auth: Bearer token (`KETRICS_TOKEN`)
365
+ - Response: Presigned S3 URL, deployment ID
234
366
 
235
- Frontend dist: /path/to/frontend/dist
236
- Backend dist: /path/to/backend/dist
237
- ```
367
+ 2. **AWS S3**:
368
+ - Upload method: HTTP PUT to presigned URL
369
+ - Content-Type: `application/zip`
370
+ - Max upload timeout: 5 minutes
238
371
 
239
- ### Deploy Command
372
+ 3. **Data Plane API** (via `ketrics run`):
373
+ - Endpoint: User-defined in JSON config files
374
+ - Auth: Bearer token (`KETRICS_AUTH_TOKEN`)
240
375
 
241
- ```
242
- $ ketrics deploy
376
+ ---
243
377
 
244
- Ketrics CLI v1.0.0
378
+ ## 4. Data Flow
245
379
 
246
- Loaded environment configuration
247
- ✔ Validated deployment token
380
+ ### Create Command Flow
248
381
 
249
- Building frontend and backend...
382
+ ```
383
+ User Input (app name)
384
+
385
+
386
+ ┌───────────────────┐
387
+ │ Validate Name │ ── Invalid ──▶ Exit with error
388
+ └───────────────────┘
389
+ │ Valid
390
+
391
+ ┌───────────────────┐
392
+ │ Check Dest Dir │ ── Exists ──▶ Exit with error
393
+ └───────────────────┘
394
+ │ OK
395
+
396
+ ┌───────────────────┐
397
+ │ List Templates │ ◀── Scan templates/ directory
398
+ └───────────────────┘
399
+
400
+
401
+ ┌───────────────────┐
402
+ │ Select Template │ ◀── Interactive prompt or --template flag
403
+ └───────────────────┘
404
+
405
+
406
+ ┌───────────────────┐
407
+ │ Copy Files │ ── Recursive copy to dest dir
408
+ └───────────────────┘
409
+
410
+
411
+ ┌───────────────────┐
412
+ │ Update App Name │ ── Modify JSON files in-place
413
+ └───────────────────┘
414
+
415
+
416
+ Success message with next steps
417
+ ```
250
418
 
251
- > frontend build output...
252
- > backend build output...
419
+ ### Deploy Command Flow
253
420
 
254
- ✔ Frontend and backend built successfully
255
- Created deployment ZIP archive
256
- ✔ ZIP archive: 59.9 KB from 5 files
257
- ✔ Initiated deployment
258
- ✔ Uploaded to S3
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
+ ```
259
474
 
260
- Deployment successful!
475
+ ### Run Command Flow
261
476
 
262
- Deployment ID: 550e8400-e29b-41d4-a716-446655440002
263
- Files: 5
264
- Size: 59.9 KB
265
- Duration: 3.2s
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
+ ```
266
515
 
267
- Your deployment is being processed by Ketrics.
516
+ ---
517
+
518
+ ## 5. Error Handling
519
+
520
+ ### Error Scenarios
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" |
540
+
541
+ ### Retry Logic
542
+
543
+ The CLI does **not** implement automatic retry for API calls. Network failures result in immediate error and process exit. This is intentional—deployments are explicit actions where the developer should understand and resolve any connectivity issues before retrying.
544
+
545
+ ### Logging Approach
546
+
547
+ All user-facing output goes through `src/utils/logger.ts`:
548
+
549
+ ```typescript
550
+ logger.info(message) // Blue ℹ prefix
551
+ logger.success(message) // Green ✔ prefix
552
+ logger.warn(message) // Yellow ⚠ prefix
553
+ logger.error(message) // Red ✖ prefix
554
+ logger.keyValue(k, v) // Formatted key: value pairs
555
+ logger.file(path, size) // Cyan file path with optional size
556
+ logger.box(title, [...])// Green success box with details
268
557
  ```
269
558
 
270
- ### Dry Run
559
+ Long-running operations use spinners (`src/utils/spinner.ts`):
271
560
 
561
+ ```typescript
562
+ await withSpinner(
563
+ "Loading environment configuration", // Shown during operation
564
+ async () => loadEnvConfig(options.env),
565
+ "Loaded environment configuration", // Shown on success
566
+ );
272
567
  ```
273
- $ ketrics deploy --dry-run
274
568
 
275
- Ketrics CLI v1.0.0
569
+ Build output is passed through to the terminal via `stdio: 'inherit'` in `execSync`, so developers see native npm/Vite/TypeScript output.
276
570
 
277
- ✔ Loaded environment configuration
278
- ✔ Validated deployment token
571
+ ---
279
572
 
280
- Building frontend and backend...
281
- ✔ Frontend and backend built successfully
573
+ ## 6. Usage
282
574
 
283
- Dry run - no files were uploaded
575
+ ### Installation
284
576
 
285
- Files to deploy:
286
- frontend/
287
- assets/index-xxx.js (192.8 KB)
288
- assets/index-xxx.css (1.4 KB)
289
- index.html (471 B)
577
+ ```bash
578
+ # Global installation
579
+ npm install -g @ketrics/ketrics-cli
290
580
 
291
- backend/
292
- index.d.ts (1.2 KB)
293
- index.js (3.4 KB)
581
+ # Or run directly with npx
582
+ npx @ketrics/ketrics-cli deploy
294
583
 
295
- Total files: 5
296
- Frontend files: 3
297
- Backend files: 2
298
- Source size: 199.3 KB
299
- ZIP size: 59.9 KB
584
+ # Development installation (from source)
585
+ cd ketrics-cli
586
+ npm install
587
+ npm run build
588
+ npm link
300
589
  ```
301
590
 
302
- ## Error Handling
591
+ ### Commands
303
592
 
304
- ### Missing node_modules
593
+ #### Create New Application
305
594
 
595
+ ```bash
596
+ # Interactive template selection
597
+ ketrics create my-app
598
+
599
+ # Use specific template
600
+ ketrics create my-app --template ketrics-app-v1
306
601
  ```
307
- ✖ Missing node_modules in frontend/. Run 'cd frontend && npm install' first.
602
+
603
+ #### Build Without Deploying
604
+
605
+ ```bash
606
+ ketrics build
308
607
  ```
309
608
 
310
- ### Folder already exists
609
+ #### Deploy to Platform
610
+
611
+ ```bash
612
+ # Standard deployment
613
+ ketrics deploy
311
614
 
615
+ # Use specific .env file
616
+ ketrics deploy --env /path/to/.env
617
+
618
+ # Preview what would be deployed (no upload)
619
+ ketrics deploy --dry-run
312
620
  ```
313
- $ ketrics create my-app
314
- Folder 'my-app' already exists.
621
+
622
+ #### Validate Configuration
623
+
624
+ ```bash
625
+ # Validate default files
626
+ ketrics validate
627
+
628
+ # Validate specific files
629
+ ketrics validate --config ./custom.config.json --env ./custom.env
315
630
  ```
316
631
 
317
- ### Invalid app name
632
+ #### Execute API Request
633
+
634
+ ```bash
635
+ # Run test request from JSON file
636
+ ketrics run tests/test.greet.json
318
637
 
638
+ # With custom .env and verbose output
639
+ ketrics run tests/test.echo.json --env .env.local --verbose
319
640
  ```
320
- $ ketrics create 123-invalid
321
- App name must start with a letter and contain only letters, numbers, hyphens, and underscores
641
+
642
+ ### Example Run File
643
+
644
+ `tests/test.greet.json`:
645
+
646
+ ```json
647
+ {
648
+ "endpoint": "/tenants/{{tenantId}}/applications/{{applicationId}}/functions/greet",
649
+ "method": "POST",
650
+ "headers": {
651
+ "Authorization": "Bearer {{token}}",
652
+ "Content-Type": "application/json"
653
+ },
654
+ "body": {
655
+ "name": "World"
656
+ }
657
+ }
658
+ ```
659
+
660
+ ### Development Commands
661
+
662
+ ```bash
663
+ # Build TypeScript to dist/
664
+ npm run build
665
+
666
+ # Run CLI in development mode (ts-node)
667
+ npm run dev -- create my-app
668
+ npm run dev -- deploy --dry-run
669
+
670
+ # Clean build artifacts
671
+ npm run clean
322
672
  ```
323
673
 
324
- ## License
674
+ ### Testing Approach
675
+
676
+ The CLI does not include automated tests in the current implementation. Testing is performed manually:
677
+
678
+ 1. **Unit testing config validation**: Create various `.env` and `ketrics.config.json` files with valid/invalid data, run `ketrics validate`
679
+ 2. **Integration testing deployment**:
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
325
686
 
326
- MIT
687
+ ### Example Session
688
+
689
+ ```bash
690
+ # Create a new application
691
+ $ ketrics create hello-world
692
+
693
+ Creating 'hello-world' with template: ketrics-app-v1
694
+
695
+ Files to create:
696
+ hello-world/ketrics.config.json
697
+ hello-world/frontend/package.json
698
+ hello-world/backend/package.json
699
+ ...
700
+
701
+ ✔ Created 'hello-world' successfully!
702
+
703
+ Next steps:
704
+ 1. cd hello-world
705
+ 2. cd frontend && npm install
706
+ 3. cd ../backend && npm install
707
+ 4. Copy .env.example to .env and add your credentials
708
+ 5. Run 'ketrics deploy' to deploy your application
709
+
710
+ # Install dependencies
711
+ $ cd hello-world
712
+ $ cd frontend && npm install && cd ../backend && npm install
713
+
714
+ # Configure credentials
715
+ $ cp .env.example .env
716
+ $ vim .env # Add your KETRICS_TOKEN, etc.
717
+
718
+ # Deploy
719
+ $ ketrics deploy
720
+
721
+ Ketrics CLI v1.0.0
722
+
723
+ ✔ Loaded environment configuration
724
+ ✔ Validated deployment token
725
+
726
+ Building frontend and backend...
727
+
728
+ > hello-world@1.0.0 build
729
+ > vite build
730
+ ...
731
+
732
+ ✔ Frontend and backend built successfully
733
+ ✔ Created deployment ZIP archive
734
+ ✔ ZIP archive: 45.2 KB from 6 files
735
+ ✔ Initiated deployment
736
+ ✔ Uploaded to S3
737
+
738
+ ✅ Deployment successful!
739
+
740
+ Deployment ID: 550e8400-e29b-41d4-a716-446655440002
741
+ Files: 6
742
+ Size: 45.2 KB
743
+ Duration: 4.1s
744
+
745
+ Your deployment is being processed by Ketrics.
746
+ ```
package/dist/src/cli.d.ts CHANGED
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * Command-line interface setup using Commander.js.
5
5
  */
6
- import { Command } from 'commander';
6
+ import { Command } from "commander";
7
7
  /**
8
8
  * Create and configure CLI program
9
9
  */
package/dist/src/cli.js CHANGED
@@ -12,21 +12,21 @@ const build_1 = require("./commands/build");
12
12
  const deploy_1 = require("./commands/deploy");
13
13
  const validate_1 = require("./commands/validate");
14
14
  const run_1 = require("./commands/run");
15
- const VERSION = '1.0.0';
15
+ const VERSION = "0.1.1";
16
16
  /**
17
17
  * Create and configure CLI program
18
18
  */
19
19
  function createCLI() {
20
20
  const program = new commander_1.Command();
21
21
  program
22
- .name('ketrics')
23
- .description('CLI tool for deploying applications to Ketrics platform')
24
- .version(VERSION, '-v, --version', 'Show CLI version');
22
+ .name("ketrics")
23
+ .description("CLI tool for deploying applications to Ketrics platform")
24
+ .version(VERSION, "-v, --version", "Show CLI version");
25
25
  // Create command
26
26
  program
27
- .command('create <app-name>')
28
- .description('Create a new Ketrics application from a template')
29
- .option('-t, --template <name>', 'Use specific template (skip interactive selection)')
27
+ .command("create <app-name>")
28
+ .description("Create a new Ketrics application from a template")
29
+ .option("-t, --template <name>", "Use specific template (skip interactive selection)")
30
30
  .action(async (appName, options) => {
31
31
  await (0, create_1.createCommand)(appName, {
32
32
  template: options.template,
@@ -34,17 +34,17 @@ function createCLI() {
34
34
  });
35
35
  // Build command
36
36
  program
37
- .command('build')
38
- .description('Build frontend and backend without deploying')
37
+ .command("build")
38
+ .description("Build frontend and backend without deploying")
39
39
  .action(async () => {
40
40
  await (0, build_1.buildCommand)();
41
41
  });
42
42
  // Deploy command
43
43
  program
44
- .command('deploy')
45
- .description('Build and deploy frontend/backend to Ketrics')
46
- .option('-e, --env <path>', 'Path to .env file')
47
- .option('--dry-run', 'Build and show what would be deployed without uploading')
44
+ .command("deploy")
45
+ .description("Build and deploy frontend/backend to Ketrics")
46
+ .option("-e, --env <path>", "Path to .env file")
47
+ .option("--dry-run", "Build and show what would be deployed without uploading")
48
48
  .action(async (options) => {
49
49
  await (0, deploy_1.deployCommand)({
50
50
  env: options.env,
@@ -53,19 +53,19 @@ function createCLI() {
53
53
  });
54
54
  // Validate command
55
55
  program
56
- .command('validate')
57
- .description('Validate configuration and .env files')
58
- .option('-c, --config <path>', 'Path to ketrics.config.json')
59
- .option('-e, --env <path>', 'Path to .env file')
56
+ .command("validate")
57
+ .description("Validate configuration and .env files")
58
+ .option("-c, --config <path>", "Path to ketrics.config.json")
59
+ .option("-e, --env <path>", "Path to .env file")
60
60
  .action(async (options) => {
61
61
  await (0, validate_1.validateCommand)(options.config, options.env);
62
62
  });
63
63
  // Run command
64
64
  program
65
- .command('run <json-file>')
66
- .description('Execute an API request from a JSON configuration file')
67
- .option('-e, --env <path>', 'Path to .env file')
68
- .option('-v, --verbose', 'Show detailed request/response information')
65
+ .command("run <json-file>")
66
+ .description("Execute an API request from a JSON configuration file")
67
+ .option("-e, --env <path>", "Path to .env file")
68
+ .option("-v, --verbose", "Show detailed request/response information")
69
69
  .action(async (jsonFile, options) => {
70
70
  await (0, run_1.runCommand)(jsonFile, {
71
71
  env: options.env,
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * API Client Service
3
3
  *
4
- * HTTP client for communicating with Ketrics Control Plane API.
4
+ * HTTP client for communicating with Ketrics Tenant API.
5
5
  */
6
6
  import type { EnvConfig, DeployResponse } from "../types";
7
7
  /**
@@ -2,7 +2,7 @@
2
2
  /**
3
3
  * API Client Service
4
4
  *
5
- * HTTP client for communicating with Ketrics Control Plane API.
5
+ * HTTP client for communicating with Ketrics Tenant API.
6
6
  */
7
7
  var __importDefault = (this && this.__importDefault) || function (mod) {
8
8
  return (mod && mod.__esModule) ? mod : { "default": mod };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ketrics/ketrics-cli",
3
- "version": "0.1.0",
3
+ "version": "0.2.1",
4
4
  "description": "CLI tool for deploying applications to Ketrics platform",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -34,11 +34,11 @@
34
34
  "devDependencies": {
35
35
  "@types/archiver": "^6.0.2",
36
36
  "@types/node": "^20.10.0",
37
- "ts-node": "^10.9.2",
37
+ "ts-node": "^1.7.1",
38
38
  "typescript": "^5.3.3"
39
39
  },
40
40
  "engines": {
41
- "node": ">=18.0.0"
41
+ "node": ">=24.0.0"
42
42
  },
43
43
  "files": [
44
44
  "dist",
@@ -5,7 +5,7 @@
5
5
  KETRICS_TOKEN=ktd_your-token-id_your-secret-key
6
6
 
7
7
  # API URL (default for production)
8
- KETRICS_API_URL=https://api.ketrics.cl/api/v1
8
+ KETRICS_API_URL=https://api.ketrics.io/api/v1
9
9
 
10
10
  # Your tenant ID
11
11
  KETRICS_TENANT_ID=your-tenant-uuid
@@ -10,7 +10,7 @@ test-application/
10
10
  │ ├── src/
11
11
  │ ├── ketrics.config.json
12
12
  │ └── .env.example
13
- └── backend/ # TypeScript handlers for data-plane
13
+ └── backend/ # TypeScript handlers for runtime-api
14
14
  ├── src/
15
15
  ├── ketrics.config.json
16
16
  └── .env.example
@@ -47,7 +47,7 @@ npm run build
47
47
 
48
48
  ## Backend
49
49
 
50
- TypeScript handlers compatible with Ketrics data-plane-api.
50
+ TypeScript handlers compatible with Ketrics runtime-api-api.
51
51
 
52
52
  ### Available Actions
53
53
 
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Ketrics Application Backend
3
3
  *
4
- * Exports handler functions compatible with Ketrics data-plane-api.
4
+ * Exports handler functions compatible with Ketrics runtime-api.
5
5
  *
6
6
  * The `ketrics` global object is automatically typed via @ketrics/sdk.
7
7
  * No imports needed - just use `ketrics.*` directly.
@@ -4,7 +4,7 @@ const saveFile = async () => {
4
4
  const data = {
5
5
  id: ketrics.application.id,
6
6
  code: ketrics.application.code,
7
- name: ketrics.application.name,
7
+ applicationName: ketrics.application.applicationName,
8
8
  version: ketrics.application.version,
9
9
  deploymentId: ketrics.application.deploymentId,
10
10
  };