@startanaicompany/cli 1.4.11 → 1.4.13
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/CLAUDE.md +284 -16
- package/OAUTH_FIX_COMPLETE.md +0 -0
- package/PUBLISHING.md +0 -0
- package/README.md +0 -0
- package/auth_session_update.md +0 -0
- package/bin/saac.js +15 -2
- package/create-application-update.md +0 -0
- package/git_auth.md +0 -0
- package/package.json +1 -1
- package/src/commands/create.js +25 -39
- package/src/commands/delete.js +0 -0
- package/src/commands/deploy.js +0 -0
- package/src/commands/domain.js +0 -0
- package/src/commands/env.js +0 -0
- package/src/commands/git.js +2 -2
- package/src/commands/init.js +0 -0
- package/src/commands/list.js +0 -0
- package/src/commands/login.js +0 -0
- package/src/commands/logout.js +0 -0
- package/src/commands/logoutAll.js +0 -0
- package/src/commands/logs.js +0 -0
- package/src/commands/manual.js +51 -0
- package/src/commands/register.js +0 -0
- package/src/commands/sessions.js +0 -0
- package/src/commands/status.js +0 -0
- package/src/commands/update.js +11 -3
- package/src/commands/verify.js +0 -0
- package/src/commands/whoami.js +0 -0
- package/src/lib/api.js +0 -0
- package/src/lib/config.js +0 -0
- package/src/lib/logger.js +0 -0
- package/src/lib/oauth.js +0 -0
- package/test-session-token.js +0 -0
package/CLAUDE.md
CHANGED
|
@@ -103,6 +103,11 @@ All commands follow this pattern:
|
|
|
103
103
|
|
|
104
104
|
**Important:** Commands require flags and do NOT use interactive prompts. This makes them LLM and automation-friendly.
|
|
105
105
|
|
|
106
|
+
**Exceptions to Non-Interactive Rule:**
|
|
107
|
+
- `saac init` - Uses inquirer to select from existing applications (intentionally interactive)
|
|
108
|
+
- `saac logout-all` - Confirmation prompt (can be skipped with `-y` flag)
|
|
109
|
+
- `saac git connect` - Interactive provider selection when no host specified
|
|
110
|
+
|
|
106
111
|
**Examples:**
|
|
107
112
|
```bash
|
|
108
113
|
# ✅ Correct - with flags
|
|
@@ -115,10 +120,11 @@ saac login
|
|
|
115
120
|
```
|
|
116
121
|
|
|
117
122
|
**Command Files**:
|
|
118
|
-
- Authentication: `register.js`, `login.js`, `verify.js`, `logout.js`, `whoami.js`
|
|
119
|
-
-
|
|
120
|
-
-
|
|
121
|
-
-
|
|
123
|
+
- Authentication: `register.js`, `login.js`, `verify.js`, `logout.js`, `logoutAll.js`, `sessions.js`, `whoami.js` (stub)
|
|
124
|
+
- Git OAuth: `git.js` (exports object with `connect`, `list`, `disconnect` methods)
|
|
125
|
+
- App Management: `create.js`, `init.js`, `deploy.js`, `update.js`, `delete.js` (stub), `list.js`, `status.js`
|
|
126
|
+
- Configuration: `env.js` (stub), `domain.js` (stub)
|
|
127
|
+
- Logs: `logs.js` (stub)
|
|
122
128
|
|
|
123
129
|
### Entry Point (`bin/saac.js`)
|
|
124
130
|
|
|
@@ -361,9 +367,33 @@ saac git disconnect git.startanaicompany.com
|
|
|
361
367
|
- ✅ Supports multiple Git providers
|
|
362
368
|
|
|
363
369
|
**Implementation Files:**
|
|
364
|
-
- `src/lib/oauth.js` - OAuth helper functions
|
|
365
|
-
- `src/commands/git.js` - Git command implementation
|
|
366
|
-
- Updated `src/commands/create.js` - OAuth integration
|
|
370
|
+
- `src/lib/oauth.js` - OAuth helper functions (exports: `extractGitHost`, `connectGitAccount`, `getConnection`, `listConnections`, `revokeConnection`)
|
|
371
|
+
- `src/commands/git.js` - Git command implementation (exports object with `connect`, `list`, `disconnect` methods)
|
|
372
|
+
- Updated `src/commands/create.js` - OAuth integration (checks for existing OAuth connection before requiring `--git-token`)
|
|
373
|
+
|
|
374
|
+
### Deploy Command Implementation
|
|
375
|
+
|
|
376
|
+
The `deploy` command triggers deployment for the current application.
|
|
377
|
+
|
|
378
|
+
**Usage:**
|
|
379
|
+
```bash
|
|
380
|
+
saac deploy
|
|
381
|
+
saac deploy --force
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
**How It Works:**
|
|
385
|
+
1. Validates authentication (session token not expired)
|
|
386
|
+
2. Checks for project config (`.saac/config.json`)
|
|
387
|
+
3. Makes POST request to `/api/v1/applications/:uuid/deploy`
|
|
388
|
+
4. Displays deployment status and deployment ID
|
|
389
|
+
5. Shows command to follow logs: `saac logs --follow`
|
|
390
|
+
|
|
391
|
+
**Response Fields:**
|
|
392
|
+
- `status` - Application status after deployment triggered
|
|
393
|
+
- `domain` - Application domain (if available)
|
|
394
|
+
- `deployment_id` - Unique ID for this deployment
|
|
395
|
+
|
|
396
|
+
**Note:** The `--force` flag is defined in the CLI but not currently used by the API.
|
|
367
397
|
|
|
368
398
|
### Init Command Implementation
|
|
369
399
|
|
|
@@ -392,25 +422,58 @@ saac init
|
|
|
392
422
|
|
|
393
423
|
**Note:** The `init` command options (`-n, --name`, etc.) are currently not implemented. To create a new application, use `saac create` instead.
|
|
394
424
|
|
|
425
|
+
### List Command Implementation
|
|
426
|
+
|
|
427
|
+
The `list` command displays all user applications in a formatted table.
|
|
428
|
+
|
|
429
|
+
**Usage:**
|
|
430
|
+
```bash
|
|
431
|
+
saac list
|
|
432
|
+
saac ls # Alias
|
|
433
|
+
```
|
|
434
|
+
|
|
435
|
+
**How It Works:**
|
|
436
|
+
1. Validates authentication
|
|
437
|
+
2. Fetches all applications from `/api/v1/applications`
|
|
438
|
+
3. Displays table with columns: Name, Domain, Status, Branch, Created
|
|
439
|
+
4. Shows total count and helpful next-step commands
|
|
440
|
+
|
|
441
|
+
**Status Display:**
|
|
442
|
+
Uses the same status display logic as the status command (see "Application Status Values" section).
|
|
443
|
+
|
|
444
|
+
**Table Formatting:**
|
|
445
|
+
- Uses the `table` npm package
|
|
446
|
+
- Header shows total application count
|
|
447
|
+
- Domains fallback to `{subdomain}.startanaicompany.com` if not set
|
|
448
|
+
- Branch defaults to 'master' if not specified
|
|
449
|
+
|
|
395
450
|
### Incomplete Commands
|
|
396
451
|
|
|
397
452
|
Several commands still need implementation:
|
|
398
|
-
- `src/commands/env.js` - Not implemented (
|
|
399
|
-
- `src/commands/domain.js` - Not implemented (
|
|
400
|
-
- `src/commands/logs.js` - Not implemented (
|
|
401
|
-
- `src/commands/delete.js` - Not implemented (
|
|
402
|
-
- `src/commands/
|
|
403
|
-
- `src/commands/whoami.js` - Not implemented (partial stub)
|
|
453
|
+
- `src/commands/env.js` - Not implemented (stub only)
|
|
454
|
+
- `src/commands/domain.js` - Not implemented (stub only)
|
|
455
|
+
- `src/commands/logs.js` - Not implemented (stub only)
|
|
456
|
+
- `src/commands/delete.js` - Not implemented (stub only)
|
|
457
|
+
- `src/commands/whoami.js` - Not implemented (stub only)
|
|
404
458
|
|
|
405
|
-
|
|
459
|
+
**Important:** The `env` and `domain` commands need to export OBJECTS with subcommand methods (e.g., `module.exports = { set, get, list }`), not simple functions. See `bin/saac.js:189-219` for how these are called.
|
|
406
460
|
|
|
407
461
|
**Implementation Pattern for New Commands:**
|
|
408
|
-
1. Require flags, no interactive prompts
|
|
462
|
+
1. Require flags, no interactive prompts (exception: `init` uses inquirer for app selection)
|
|
409
463
|
2. Show usage info if required flags missing
|
|
410
464
|
3. Validate inputs before API calls
|
|
411
465
|
4. Use spinners for async operations
|
|
412
466
|
5. Handle errors with descriptive messages
|
|
413
467
|
|
|
468
|
+
**Example Module Structure for env.js:**
|
|
469
|
+
```javascript
|
|
470
|
+
async function set(vars) { /* implementation */ }
|
|
471
|
+
async function get(key) { /* implementation */ }
|
|
472
|
+
async function list() { /* implementation */ }
|
|
473
|
+
|
|
474
|
+
module.exports = { set, get, list };
|
|
475
|
+
```
|
|
476
|
+
|
|
414
477
|
### MailHog Integration
|
|
415
478
|
|
|
416
479
|
The system uses MailHog for email verification in development:
|
|
@@ -430,7 +493,183 @@ The wrapper API expects Git repositories to be hosted on the StartAnAiCompany Gi
|
|
|
430
493
|
- During registration, Gitea username can be auto-detected or manually provided
|
|
431
494
|
- Applications reference repositories in the format: `git@git.startanaicompany.com:user/repo.git`
|
|
432
495
|
|
|
433
|
-
##
|
|
496
|
+
## Current Status - Version 1.4.13
|
|
497
|
+
|
|
498
|
+
### Completed Features
|
|
499
|
+
|
|
500
|
+
**Authentication & Sessions:**
|
|
501
|
+
- ✅ `saac register` - Register with email only (git_username auto-detected from email)
|
|
502
|
+
- ✅ `saac login` - Login with email + API key, receives 1-year session token
|
|
503
|
+
- ✅ `saac verify` - Email verification, shows FULL API key for user to save
|
|
504
|
+
- ✅ `saac logout` - Logout from current device
|
|
505
|
+
- ✅ `saac logout-all` - Revoke all sessions
|
|
506
|
+
- ✅ `saac sessions` - List all active sessions
|
|
507
|
+
- ✅ `saac whoami` - Show current user info
|
|
508
|
+
|
|
509
|
+
**Git OAuth (NEW in 1.4.0):**
|
|
510
|
+
- ✅ `saac git connect [host]` - OAuth flow for Git authentication
|
|
511
|
+
- ✅ `saac git list` - List connected Git accounts
|
|
512
|
+
- ✅ `saac git disconnect <host>` - Revoke Git connection
|
|
513
|
+
- ✅ OAuth integration in create command (prompts if not connected)
|
|
514
|
+
|
|
515
|
+
**Application Management:**
|
|
516
|
+
- ✅ `saac create` - Create application with ALL advanced features
|
|
517
|
+
- ✅ `saac update` - Update application configuration (PATCH endpoint)
|
|
518
|
+
- ✅ `saac init` - Link existing application to current directory (interactive)
|
|
519
|
+
- ✅ `saac deploy` - Trigger deployment for current application
|
|
520
|
+
- ✅ `saac list` - List all applications with table display
|
|
521
|
+
- ✅ `saac status` - Show login status, user info, and applications
|
|
522
|
+
|
|
523
|
+
**Incomplete Commands:**
|
|
524
|
+
- ⏳ `saac logs` - Not implemented (stub only)
|
|
525
|
+
- ⏳ `saac env` - Not implemented (stub only, needs to export object with set/get/list methods)
|
|
526
|
+
- ⏳ `saac domain` - Not implemented (stub only, needs to export object with set/show methods)
|
|
527
|
+
- ⏳ `saac delete` - Not implemented (stub only)
|
|
528
|
+
- ⏳ `saac whoami` - Not implemented (stub only)
|
|
529
|
+
- ✅ `saac deploy` - Fully implemented
|
|
530
|
+
- ✅ `saac list` - Fully implemented
|
|
531
|
+
|
|
532
|
+
### Critical Learnings & Bug Fixes
|
|
533
|
+
|
|
534
|
+
**Issue 1: Config Location**
|
|
535
|
+
- **Problem:** Conf package auto-appended `-nodejs` suffix to folder name
|
|
536
|
+
- **Solution:** Use explicit `cwd: path.join(os.homedir(), '.config', 'startanaicompany')` instead of `projectName`
|
|
537
|
+
- **Location:** `src/lib/config.js`
|
|
538
|
+
|
|
539
|
+
**Issue 2: Status Command Showing "Logged in" Then "Expired"**
|
|
540
|
+
- **Problem:** Command checked local session first, displayed status, THEN verified with server
|
|
541
|
+
- **Solution:** Verify with server FIRST before displaying any status
|
|
542
|
+
- **Location:** `src/commands/status.js`
|
|
543
|
+
|
|
544
|
+
**Issue 3: Application List Inconsistency**
|
|
545
|
+
- **Problem:** `/users/me` returned `application_count: 1` but `/applications` returned empty array
|
|
546
|
+
- **Root Cause:** Backend filtered by `status='active'` but new apps start with `status='creating'`
|
|
547
|
+
- **Solution:** Backend team fixed to filter by `status != 'deleted'`
|
|
548
|
+
- **Location:** Backend - `src/services/application.js:447`
|
|
549
|
+
|
|
550
|
+
**Issue 4: Register Endpoint 404 Error**
|
|
551
|
+
- **Problem:** CLI was calling `POST /api/v1/register` but actual endpoint is `POST /api/v1/users/register`
|
|
552
|
+
- **Solution:** Changed endpoint path in api.js
|
|
553
|
+
- **Location:** `src/lib/api.js:64`
|
|
554
|
+
|
|
555
|
+
**Issue 5: Deprecated Field Names**
|
|
556
|
+
- **Problem:** CLI still used `gitea_username` and `gitea_api_token`
|
|
557
|
+
- **Solution:** Renamed to `git_username` and `git_api_token` throughout codebase
|
|
558
|
+
- **Affected:** `register.js`, `api.js`, `bin/saac.js`
|
|
559
|
+
|
|
560
|
+
**Issue 6: Truncated API Key Display**
|
|
561
|
+
- **Problem:** Showing truncated API key with "Save this key" message was confusing
|
|
562
|
+
- **Solution:** Show FULL API key in verify command (it's only shown once)
|
|
563
|
+
- **Location:** `src/commands/verify.js:72`
|
|
564
|
+
|
|
565
|
+
**Issue 7: Git Username Auto-Detection**
|
|
566
|
+
- **Finding:** Server auto-populates `git_username` from email address (e.g., `kalle.johansson@goryan.io` → `kalle.johansson`)
|
|
567
|
+
- **Behavior:** This is backend behavior, CLI just displays what server returns
|
|
568
|
+
- **No action needed:** Working as designed
|
|
569
|
+
|
|
570
|
+
### API Endpoint Reference
|
|
571
|
+
|
|
572
|
+
**Correct Endpoint Paths (v1.4.12):**
|
|
573
|
+
- `POST /api/v1/users/register` - Register (email only, git_username optional)
|
|
574
|
+
- `POST /api/v1/users/verify` - Verify email with code
|
|
575
|
+
- `POST /api/v1/auth/login` - Login with API key, get session token
|
|
576
|
+
- `POST /api/v1/auth/logout` - Logout current session
|
|
577
|
+
- `POST /api/v1/auth/logout-all` - Revoke all sessions
|
|
578
|
+
- `GET /api/v1/auth/sessions` - List all sessions
|
|
579
|
+
- `GET /api/v1/users/me` - Get user info
|
|
580
|
+
- `GET /api/v1/users/me/oauth` - List OAuth connections
|
|
581
|
+
- `DELETE /api/v1/users/me/oauth/:git_host` - Revoke OAuth connection
|
|
582
|
+
- `GET /oauth/authorize` - Initiate OAuth flow (no /api/v1 prefix!)
|
|
583
|
+
- `GET /oauth/poll/:session_id` - Poll OAuth status (no /api/v1 prefix!)
|
|
584
|
+
- `POST /api/v1/applications` - Create application
|
|
585
|
+
- `GET /api/v1/applications` - List applications
|
|
586
|
+
- `PATCH /api/v1/applications/:uuid` - Update application
|
|
587
|
+
- `POST /api/v1/applications/:uuid/deploy` - Deploy application
|
|
588
|
+
- `GET /api/v1/applications/:uuid/logs` - Get logs
|
|
589
|
+
- `DELETE /api/v1/applications/:uuid` - Delete application
|
|
590
|
+
|
|
591
|
+
**Important:** OAuth endpoints (`/oauth/*`) do NOT have the `/api/v1` prefix!
|
|
592
|
+
|
|
593
|
+
### OAuth Implementation Details
|
|
594
|
+
|
|
595
|
+
**Token Handling:**
|
|
596
|
+
- Session tokens start with `st_`
|
|
597
|
+
- API keys start with `cw_`
|
|
598
|
+
- OAuth helper functions detect token type and use correct header:
|
|
599
|
+
- `st_*` → `X-Session-Token`
|
|
600
|
+
- `cw_*` → `X-API-Key`
|
|
601
|
+
|
|
602
|
+
**Polling Strategy:**
|
|
603
|
+
- Initial 60-second wait before polling starts (gives user time to complete OAuth)
|
|
604
|
+
- Poll every 2 seconds for up to 5 minutes
|
|
605
|
+
- Handles 401/404 errors during polling (expected while user authorizes)
|
|
606
|
+
- Only fails on non-auth errors (500, network errors)
|
|
607
|
+
|
|
608
|
+
**OAuth URL Construction:**
|
|
609
|
+
- Remove `/api/v1` suffix from base URL: `baseUrl.replace('/api/v1', '')`
|
|
610
|
+
- OAuth endpoints: `${baseUrl}/oauth/authorize` and `${baseUrl}/oauth/poll/:id`
|
|
611
|
+
|
|
612
|
+
### Application Status Values
|
|
613
|
+
|
|
614
|
+
Backend returns these status values (from Coolify):
|
|
615
|
+
- `creating` - Application being created (initial state)
|
|
616
|
+
- `active` - Fully created and operational
|
|
617
|
+
- `running:healthy` - Container running and healthy
|
|
618
|
+
- `running:unknown` - Container running, health status unknown
|
|
619
|
+
- `stopped` - Container stopped
|
|
620
|
+
- `error` - Creation or deployment failed
|
|
621
|
+
- `suspended` - Suspended by admin
|
|
622
|
+
|
|
623
|
+
**CLI Display Logic:**
|
|
624
|
+
```javascript
|
|
625
|
+
if (status.startsWith('running')) {
|
|
626
|
+
display = 'Running ✓' (green);
|
|
627
|
+
} else if (status.startsWith('stopped')) {
|
|
628
|
+
display = 'Stopped' (yellow);
|
|
629
|
+
} else {
|
|
630
|
+
switch (status) {
|
|
631
|
+
case 'active': display = 'Active ✓' (green);
|
|
632
|
+
case 'creating': display = 'Creating...' (yellow);
|
|
633
|
+
case 'error': display = 'Error ✗' (red);
|
|
634
|
+
case 'suspended': display = 'Suspended ⚠' (yellow);
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
```
|
|
638
|
+
|
|
639
|
+
### User Registration & Authentication Flow
|
|
640
|
+
|
|
641
|
+
**Complete Flow:**
|
|
642
|
+
1. `saac register -e user@example.com` → Creates account, sends verification email
|
|
643
|
+
2. Check MailHog at https://mailhog.goryan.io for verification code
|
|
644
|
+
3. `saac verify 123456` → Verifies email, returns API key (shown in full, only once)
|
|
645
|
+
4. `saac login -e user@example.com -k cw_...` → Exchanges API key for 1-year session token
|
|
646
|
+
5. Session token saved to `~/.config/startanaicompany/config.json`
|
|
647
|
+
6. All future commands use session token automatically
|
|
648
|
+
|
|
649
|
+
**Note:** User MUST login after verification to get session token. Verification only provides API key.
|
|
650
|
+
|
|
651
|
+
### Sessions Management Commands
|
|
652
|
+
|
|
653
|
+
**Sessions Command (`saac sessions`):**
|
|
654
|
+
- Lists all active sessions with creation date, last used time, IP address, and expiration
|
|
655
|
+
- Uses table format for clear display
|
|
656
|
+
- Shows total session count
|
|
657
|
+
- Located in `src/commands/sessions.js`
|
|
658
|
+
|
|
659
|
+
**Logout All Command (`saac logout-all`):**
|
|
660
|
+
- Revokes ALL session tokens across all devices
|
|
661
|
+
- Requires confirmation prompt unless `--yes` flag provided
|
|
662
|
+
- Clears local config after successful revocation
|
|
663
|
+
- Shows count of sessions revoked
|
|
664
|
+
- Located in `src/commands/logoutAll.js`
|
|
665
|
+
- **Exception to non-interactive rule:** Uses inquirer for confirmation prompt (but can be skipped with `-y`)
|
|
666
|
+
|
|
667
|
+
**Implementation Notes:**
|
|
668
|
+
- Both commands check authentication before proceeding
|
|
669
|
+
- Handle gracefully if session already expired (401 errors)
|
|
670
|
+
- Clear local config even if server call fails
|
|
671
|
+
|
|
672
|
+
### Testing Considerations
|
|
434
673
|
|
|
435
674
|
When implementing new commands:
|
|
436
675
|
1. Test both with flags and interactive prompts
|
|
@@ -439,3 +678,32 @@ When implementing new commands:
|
|
|
439
678
|
4. Test API error responses
|
|
440
679
|
5. Ensure proper exit codes (0 for success, 1 for errors)
|
|
441
680
|
6. Check that spinners succeed/fail appropriately
|
|
681
|
+
7. **NEVER truncate sensitive data if user needs to save it** (API keys, session tokens)
|
|
682
|
+
8. Show full values for one-time credentials
|
|
683
|
+
|
|
684
|
+
### Publishing Checklist
|
|
685
|
+
|
|
686
|
+
Before publishing to npm:
|
|
687
|
+
1. Verify all new commands work with live backend
|
|
688
|
+
2. Test OAuth flow end-to-end
|
|
689
|
+
3. Check syntax: `node -c src/**/*.js bin/*.js`
|
|
690
|
+
4. Update version in package.json
|
|
691
|
+
5. Update CLAUDE.md with changes
|
|
692
|
+
6. Run: `npm publish --access public --otp=<code>`
|
|
693
|
+
|
|
694
|
+
### Dependencies
|
|
695
|
+
|
|
696
|
+
**Required packages:**
|
|
697
|
+
- `axios` - HTTP client for API calls
|
|
698
|
+
- `chalk` - Terminal colors
|
|
699
|
+
- `commander` - CLI framework
|
|
700
|
+
- `conf` - Configuration management
|
|
701
|
+
- `inquirer` - Interactive prompts
|
|
702
|
+
- `ora` - Spinners
|
|
703
|
+
- `boxen` - Boxed messages
|
|
704
|
+
- `table` - Table display
|
|
705
|
+
- `validator` - Email validation
|
|
706
|
+
- `dotenv` - Environment variables
|
|
707
|
+
- `open` - Open browser for OAuth (v8.4.2 for compatibility with chalk v4)
|
|
708
|
+
|
|
709
|
+
**Version:** 1.4.13 (current)
|
package/OAUTH_FIX_COMPLETE.md
CHANGED
|
File without changes
|
package/PUBLISHING.md
CHANGED
|
File without changes
|
package/README.md
CHANGED
|
File without changes
|
package/auth_session_update.md
CHANGED
|
File without changes
|
package/bin/saac.js
CHANGED
|
@@ -28,13 +28,21 @@ const deleteCmd = require('../src/commands/delete');
|
|
|
28
28
|
const list = require('../src/commands/list');
|
|
29
29
|
const status = require('../src/commands/status');
|
|
30
30
|
const whoami = require('../src/commands/whoami');
|
|
31
|
+
const manual = require('../src/commands/manual');
|
|
31
32
|
|
|
32
33
|
// Configure CLI
|
|
33
34
|
program
|
|
34
35
|
.name('saac')
|
|
35
36
|
.description(chalk.cyan('Official CLI for StartAnAiCompany.com'))
|
|
36
37
|
.version(pkg.version, '-v, --version', 'Output the current version')
|
|
37
|
-
.helpOption('-h, --help', 'Display help for command')
|
|
38
|
+
.helpOption('-h, --help', 'Display help for command')
|
|
39
|
+
.addHelpText('after', `
|
|
40
|
+
${chalk.dim('For detailed documentation, visit:')}
|
|
41
|
+
${chalk.cyan('https://github.com/startanaicompany/cli')}
|
|
42
|
+
|
|
43
|
+
${chalk.dim('Or run:')}
|
|
44
|
+
${chalk.yellow('saac manual')} ${chalk.dim('- Display full manual from GitHub')}
|
|
45
|
+
`);
|
|
38
46
|
|
|
39
47
|
// Authentication commands
|
|
40
48
|
program
|
|
@@ -109,7 +117,6 @@ program
|
|
|
109
117
|
// Required options
|
|
110
118
|
.option('-s, --subdomain <subdomain>', 'Subdomain')
|
|
111
119
|
.option('-r, --repository <url>', 'Git repository URL (SSH format)')
|
|
112
|
-
.option('-t, --git-token <token>', 'Git API token')
|
|
113
120
|
// Basic options
|
|
114
121
|
.option('-b, --branch <branch>', 'Git branch', 'master')
|
|
115
122
|
.option('-d, --domain-suffix <suffix>', 'Domain suffix', 'startanaicompany.com')
|
|
@@ -235,6 +242,12 @@ program
|
|
|
235
242
|
.description('Show current user information')
|
|
236
243
|
.action(whoami);
|
|
237
244
|
|
|
245
|
+
// Documentation
|
|
246
|
+
program
|
|
247
|
+
.command('manual')
|
|
248
|
+
.description('Display full documentation from GitHub')
|
|
249
|
+
.action(manual);
|
|
250
|
+
|
|
238
251
|
// Deletion
|
|
239
252
|
program
|
|
240
253
|
.command('delete')
|
|
File without changes
|
package/git_auth.md
CHANGED
|
File without changes
|
package/package.json
CHANGED
package/src/commands/create.js
CHANGED
|
@@ -29,7 +29,6 @@ async function create(name, options) {
|
|
|
29
29
|
logger.info('Required options:');
|
|
30
30
|
logger.log(' -s, --subdomain <subdomain> Subdomain for your app');
|
|
31
31
|
logger.log(' -r, --repository <url> Git repository URL (SSH format)');
|
|
32
|
-
logger.log(' -t, --git-token <token> Git API token (optional if OAuth connected)');
|
|
33
32
|
logger.newline();
|
|
34
33
|
logger.info('Optional options:');
|
|
35
34
|
logger.log(' -b, --branch <branch> Git branch (default: master)');
|
|
@@ -51,9 +50,9 @@ async function create(name, options) {
|
|
|
51
50
|
logger.log(' --env <KEY=VALUE> Environment variable (can be used multiple times)');
|
|
52
51
|
logger.newline();
|
|
53
52
|
logger.info('Example:');
|
|
54
|
-
logger.log(' saac create my-app -s myapp -r git@git.startanaicompany.com:user/repo.git
|
|
55
|
-
logger.log(' saac create api -s api -r git@git...
|
|
56
|
-
logger.log(' saac create web -s web -r git@git...
|
|
53
|
+
logger.log(' saac create my-app -s myapp -r git@git.startanaicompany.com:user/repo.git');
|
|
54
|
+
logger.log(' saac create api -s api -r git@git... --build-pack nixpacks --port 8080');
|
|
55
|
+
logger.log(' saac create web -s web -r git@git... --health-check --pre-deploy-cmd "npm run migrate"');
|
|
57
56
|
process.exit(1);
|
|
58
57
|
}
|
|
59
58
|
|
|
@@ -62,7 +61,8 @@ async function create(name, options) {
|
|
|
62
61
|
logger.newline();
|
|
63
62
|
logger.info('Example:');
|
|
64
63
|
logger.log(` saac create ${name} -s myapp -r git@git.startanaicompany.com:user/repo.git`);
|
|
65
|
-
logger.
|
|
64
|
+
logger.newline();
|
|
65
|
+
logger.info('Note: Git OAuth connection required. Connect with: saac git connect');
|
|
66
66
|
process.exit(1);
|
|
67
67
|
}
|
|
68
68
|
|
|
@@ -77,36 +77,16 @@ async function create(name, options) {
|
|
|
77
77
|
if (connection) {
|
|
78
78
|
logger.success(`Using connected account: ${connection.gitUsername}@${connection.gitHost}`);
|
|
79
79
|
logger.newline();
|
|
80
|
-
} else
|
|
81
|
-
// No OAuth connection
|
|
82
|
-
logger.
|
|
80
|
+
} else {
|
|
81
|
+
// No OAuth connection - must connect
|
|
82
|
+
logger.error(`Git account not connected for ${gitHost}`);
|
|
83
83
|
logger.newline();
|
|
84
|
-
|
|
85
|
-
const { shouldConnect } = await inquirer.prompt([
|
|
86
|
-
{
|
|
87
|
-
type: 'confirm',
|
|
88
|
-
name: 'shouldConnect',
|
|
89
|
-
message: 'Would you like to connect now?',
|
|
90
|
-
default: true,
|
|
91
|
-
},
|
|
92
|
-
]);
|
|
93
|
-
|
|
94
|
-
if (!shouldConnect) {
|
|
95
|
-
logger.newline();
|
|
96
|
-
logger.error('Cannot create application without Git authentication');
|
|
97
|
-
logger.newline();
|
|
98
|
-
logger.info('Options:');
|
|
99
|
-
logger.log(' 1. Connect Git account: saac git connect');
|
|
100
|
-
logger.log(' 2. Provide token: saac create ... --git-token <token>');
|
|
101
|
-
process.exit(1);
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
// Initiate OAuth flow
|
|
105
|
-
await oauth.connectGitAccount(gitHost, user.sessionToken || user.apiKey);
|
|
106
|
-
|
|
84
|
+
logger.info('Git OAuth connection is required to create applications');
|
|
107
85
|
logger.newline();
|
|
108
|
-
logger.
|
|
86
|
+
logger.info('Connect now:');
|
|
87
|
+
logger.log(' saac git connect');
|
|
109
88
|
logger.newline();
|
|
89
|
+
process.exit(1);
|
|
110
90
|
}
|
|
111
91
|
|
|
112
92
|
// Build application payload
|
|
@@ -118,10 +98,8 @@ async function create(name, options) {
|
|
|
118
98
|
git_branch: options.branch || 'master',
|
|
119
99
|
};
|
|
120
100
|
|
|
121
|
-
//
|
|
122
|
-
|
|
123
|
-
appData.git_api_token = options.gitToken;
|
|
124
|
-
}
|
|
101
|
+
// OAuth tokens are retrieved from database by wrapper
|
|
102
|
+
// No manual git_api_token field needed
|
|
125
103
|
|
|
126
104
|
// Optional: Port configuration
|
|
127
105
|
if (options.port) {
|
|
@@ -304,9 +282,17 @@ async function create(name, options) {
|
|
|
304
282
|
logger.error('Validation failed');
|
|
305
283
|
if (data.details) {
|
|
306
284
|
logger.newline();
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
285
|
+
// Backend sends details as array: [{field, message, type}, ...]
|
|
286
|
+
if (Array.isArray(data.details)) {
|
|
287
|
+
data.details.forEach((detail) => {
|
|
288
|
+
logger.log(` ${logger.chalk.yellow(detail.field)}: ${detail.message}`);
|
|
289
|
+
});
|
|
290
|
+
} else {
|
|
291
|
+
// Fallback for object format: {field: message, ...}
|
|
292
|
+
Object.entries(data.details).forEach(([field, message]) => {
|
|
293
|
+
logger.log(` ${logger.chalk.yellow(field)}: ${message}`);
|
|
294
|
+
});
|
|
295
|
+
}
|
|
310
296
|
} else {
|
|
311
297
|
logger.log(` ${data.message || data.error}`);
|
|
312
298
|
}
|
package/src/commands/delete.js
CHANGED
|
File without changes
|
package/src/commands/deploy.js
CHANGED
|
File without changes
|
package/src/commands/domain.js
CHANGED
|
File without changes
|
package/src/commands/env.js
CHANGED
|
File without changes
|
package/src/commands/git.js
CHANGED
|
@@ -95,13 +95,13 @@ async function connect(host) {
|
|
|
95
95
|
}
|
|
96
96
|
|
|
97
97
|
// Initiate OAuth flow
|
|
98
|
-
await oauth.connectGitAccount(gitHost, user.sessionToken || user.apiKey);
|
|
98
|
+
const result = await oauth.connectGitAccount(gitHost, user.sessionToken || user.apiKey);
|
|
99
99
|
|
|
100
100
|
logger.newline();
|
|
101
101
|
logger.success('Git account connected successfully!');
|
|
102
102
|
logger.newline();
|
|
103
103
|
logger.info('You can now create applications without providing --git-token:');
|
|
104
|
-
logger.log(` saac create my-app -s myapp -r git@${gitHost}
|
|
104
|
+
logger.log(` saac create my-app -s myapp -r git@${gitHost}:${result.gitUsername}/repo.git`);
|
|
105
105
|
|
|
106
106
|
} catch (error) {
|
|
107
107
|
logger.error(error.message);
|
package/src/commands/init.js
CHANGED
|
File without changes
|
package/src/commands/list.js
CHANGED
|
File without changes
|
package/src/commands/login.js
CHANGED
|
File without changes
|
package/src/commands/logout.js
CHANGED
|
File without changes
|
|
File without changes
|
package/src/commands/logs.js
CHANGED
|
File without changes
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Manual command - Display full documentation from GitHub
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
const axios = require('axios');
|
|
6
|
+
const logger = require('../lib/logger');
|
|
7
|
+
|
|
8
|
+
async function manual() {
|
|
9
|
+
try {
|
|
10
|
+
logger.section('SAAC CLI Manual');
|
|
11
|
+
logger.newline();
|
|
12
|
+
|
|
13
|
+
const spin = logger.spinner('Fetching documentation from GitHub...').start();
|
|
14
|
+
|
|
15
|
+
try {
|
|
16
|
+
// Fetch README from GitHub
|
|
17
|
+
const response = await axios.get(
|
|
18
|
+
'https://raw.githubusercontent.com/startanaicompany/cli/master/README.md',
|
|
19
|
+
{ timeout: 10000 }
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
spin.succeed('Documentation loaded');
|
|
23
|
+
logger.newline();
|
|
24
|
+
|
|
25
|
+
// Display the README content
|
|
26
|
+
console.log(response.data);
|
|
27
|
+
|
|
28
|
+
logger.newline();
|
|
29
|
+
logger.info('Online documentation: https://github.com/startanaicompany/cli');
|
|
30
|
+
|
|
31
|
+
} catch (error) {
|
|
32
|
+
spin.fail('Failed to fetch documentation');
|
|
33
|
+
|
|
34
|
+
logger.newline();
|
|
35
|
+
logger.error('Could not fetch README from GitHub');
|
|
36
|
+
logger.newline();
|
|
37
|
+
logger.info('Visit the documentation online:');
|
|
38
|
+
logger.log(' https://github.com/startanaicompany/cli');
|
|
39
|
+
logger.newline();
|
|
40
|
+
logger.info('Or run:');
|
|
41
|
+
logger.log(' saac --help');
|
|
42
|
+
|
|
43
|
+
process.exit(1);
|
|
44
|
+
}
|
|
45
|
+
} catch (error) {
|
|
46
|
+
logger.error(error.message);
|
|
47
|
+
process.exit(1);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
module.exports = manual;
|
package/src/commands/register.js
CHANGED
|
File without changes
|
package/src/commands/sessions.js
CHANGED
|
File without changes
|
package/src/commands/status.js
CHANGED
|
File without changes
|
package/src/commands/update.js
CHANGED
|
@@ -259,9 +259,17 @@ async function update(options) {
|
|
|
259
259
|
logger.error('Validation failed');
|
|
260
260
|
if (data.details) {
|
|
261
261
|
logger.newline();
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
262
|
+
// Backend sends details as array: [{field, message, type}, ...]
|
|
263
|
+
if (Array.isArray(data.details)) {
|
|
264
|
+
data.details.forEach((detail) => {
|
|
265
|
+
logger.log(` ${logger.chalk.yellow(detail.field)}: ${detail.message}`);
|
|
266
|
+
});
|
|
267
|
+
} else {
|
|
268
|
+
// Fallback for object format: {field: message, ...}
|
|
269
|
+
Object.entries(data.details).forEach(([field, message]) => {
|
|
270
|
+
logger.log(` ${logger.chalk.yellow(field)}: ${message}`);
|
|
271
|
+
});
|
|
272
|
+
}
|
|
265
273
|
} else {
|
|
266
274
|
logger.log(` ${data.message || data.error}`);
|
|
267
275
|
}
|
package/src/commands/verify.js
CHANGED
|
File without changes
|
package/src/commands/whoami.js
CHANGED
|
File without changes
|
package/src/lib/api.js
CHANGED
|
File without changes
|
package/src/lib/config.js
CHANGED
|
File without changes
|
package/src/lib/logger.js
CHANGED
|
File without changes
|
package/src/lib/oauth.js
CHANGED
|
File without changes
|
package/test-session-token.js
CHANGED
|
File without changes
|