Skip to content

Commit 5bcc624

Browse files
committed
Add architecture documentation and utility organization
1 parent d34f260 commit 5bcc624

File tree

6 files changed

+449
-12
lines changed

6 files changed

+449
-12
lines changed

ARCHITECTURE.md

Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
# Socket CLI Architecture
2+
3+
## Overview
4+
5+
The Socket CLI is a TypeScript-based command-line tool for security analysis and package management. It's designed with modularity and maintainability in mind, using a clear separation of concerns.
6+
7+
## Directory Structure
8+
9+
```
10+
socket-cli/
11+
├── src/ # Source code
12+
│ ├── cli.mts # Main CLI entry point
13+
│ ├── commands.mts # Command registry
14+
│ ├── constants.mts # Shared constants
15+
│ ├── types.mts # Type definitions
16+
│ ├── commands/ # Command implementations
17+
│ ├── utils/ # Shared utilities
18+
│ ├── shadow/ # Package manager shadows
19+
│ ├── sea/ # Single Executable Application
20+
│ └── external/ # External dependencies
21+
├── bin/ # Binary entry points
22+
├── dist/ # Compiled output
23+
├── scripts/ # Build and utility scripts
24+
├── test/ # Test files
25+
└── .config/ # Configuration files
26+
```
27+
28+
## Core Concepts
29+
30+
### 1. Command Pattern
31+
Each command follows a consistent pattern:
32+
- `cmd-*.mts` - CLI interface and flag parsing
33+
- `handle-*.mts` - Business logic implementation
34+
- `output-*.mts` - Output formatting
35+
- `fetch-*.mts` - API data fetching
36+
37+
### 2. Shadow Binaries
38+
The CLI can act as a shadow for npm, npx, and pnpm, intercepting and enhancing their functionality:
39+
- Located in `src/shadow/`
40+
- Provides security scanning during package operations
41+
- Transparent to the end user
42+
43+
### 3. Utils Organization
44+
Utilities are grouped by function to reduce cognitive load:
45+
- **API & Network** - API client and HTTP utilities
46+
- **Error Handling** - Centralized error types and handlers
47+
- **Output & Formatting** - Consistent output formatting
48+
- **File System** - File operations and path handling
49+
- **Package Management** - Package manager detection and operations
50+
51+
### 4. Constants Management
52+
Constants are imported from `@socketsecurity/registry` and extended with CLI-specific values:
53+
- Shared constants from registry
54+
- CLI-specific constants
55+
- Environment variables
56+
- Configuration keys
57+
58+
## Key Design Patterns
59+
60+
### Result/Either Pattern
61+
Used throughout for error handling:
62+
```typescript
63+
type CResult<T> =
64+
| { ok: true; data: T; message?: string }
65+
| { ok: false; message: string; code?: number }
66+
```
67+
68+
### Lazy Loading
69+
Heavy dependencies are loaded only when needed to improve startup time.
70+
71+
### Configuration Cascade
72+
Configuration is resolved in order:
73+
1. Command-line flags
74+
2. Environment variables
75+
3. Local config file (.socketrc)
76+
4. Global config file
77+
5. Default values
78+
79+
## Build System
80+
81+
### Rollup Configuration
82+
- Main build uses Rollup for tree-shaking and optimization
83+
- Separate configs for different build targets
84+
- JSON files are inlined during build
85+
86+
### TypeScript Compilation
87+
- Uses `.mts` extensions for ES modules
88+
- Compiled with `tsgo` for better performance
89+
- Type definitions generated separately
90+
91+
## Testing Strategy
92+
93+
### Unit Tests
94+
- Located alongside source files as `*.test.mts`
95+
- Focus on individual function behavior
96+
- Run with Vitest
97+
98+
### Integration Tests
99+
- Located in `test/integration/`
100+
- Test command flows end-to-end
101+
- Mock external API calls
102+
103+
## Performance Considerations
104+
105+
### Startup Time
106+
- Minimal dependencies loaded at startup
107+
- Commands lazy-loaded on demand
108+
- Constants use lazy getters
109+
110+
### Memory Usage
111+
- Configurable memory limits via flags
112+
- Streaming for large data sets
113+
- Efficient caching strategies
114+
115+
## Security
116+
117+
### API Token Management
118+
- Tokens never logged or displayed
119+
- Stored securely in system keychain when possible
120+
- Validated before use
121+
122+
### Package Scanning
123+
- Real-time scanning during installs
124+
- Comprehensive vulnerability database
125+
- Configurable risk policies
126+
127+
## Extension Points
128+
129+
### Custom Commands
130+
Commands can be added by:
131+
1. Creating files in `src/commands/`
132+
2. Following the command pattern
133+
3. Registering in `src/commands.mts`
134+
135+
### Plugins
136+
Future support planned for plugins via:
137+
- Standard plugin interface
138+
- Dynamic loading
139+
- Isolated execution context
140+
141+
## Best Practices
142+
143+
1. **Keep files focused** - Single responsibility per file
144+
2. **Use TypeScript strictly** - No `any` types without good reason
145+
3. **Document exports** - JSDoc for all public APIs
146+
4. **Test thoroughly** - Aim for high coverage
147+
5. **Handle errors gracefully** - Use Result pattern
148+
6. **Optimize imports** - Import only what's needed
149+
7. **Follow patterns** - Consistency reduces cognitive load
150+
151+
## Common Tasks
152+
153+
### Adding a New Command
154+
1. Create `src/commands/[name]/cmd-[name].mts`
155+
2. Implement command logic in `handle-[name].mts`
156+
3. Add output formatting in `output-[name].mts`
157+
4. Register in `src/commands.mts`
158+
5. Add tests
159+
160+
### Adding a Utility
161+
1. Choose appropriate category in `src/utils/`
162+
2. Create focused utility file
163+
3. Export from category index if applicable
164+
4. Document with JSDoc
165+
5. Add unit tests
166+
167+
### Updating Constants
168+
1. Check if constant exists in `@socketsecurity/registry`
169+
2. If shared, add to registry
170+
3. If CLI-specific, add to `src/constants.mts`
171+
4. Use descriptive names
172+
5. Group related constants

scripts/build/build-binary.mjs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,9 @@ async function checkYaoPkgNodeVersions() {
6666
const newerVersions = versions.filter(v => {
6767
const parts = v.split('.').map(Number)
6868
// Only check same major version for patch updates
69-
if (parts[0] !== currentParts[0]) return false
70-
if (parts[1] > currentParts[1]) return true
71-
if (parts[1] === currentParts[1] && parts[2] > currentParts[2]) return true
69+
if (parts[0] !== currentParts[0]) {return false}
70+
if (parts[1] > currentParts[1]) {return true}
71+
if (parts[1] === currentParts[1] && parts[2] > currentParts[2]) {return true}
7272
return false
7373
})
7474

@@ -85,9 +85,9 @@ async function checkYaoPkgNodeVersions() {
8585
console.log(colors.magenta('║') + ' 3. Update version in ' + colors.cyan('.config/socket-node.json'))
8686
console.log(colors.magenta('║'))
8787
console.log(colors.magenta('║') + ' Latest versions by major:')
88-
if (v24) console.log(colors.magenta('║') + ` Node 24: ${colors.cyan(`v${v24}`)}`)
89-
if (v22) console.log(colors.magenta('║') + ` Node 22: ${colors.cyan(`v${v22}`)}`)
90-
if (v20) console.log(colors.magenta('║') + ` Node 20: ${colors.cyan(`v${v20}`)}`)
88+
if (v24) {console.log(colors.magenta('║') + ` Node 24: ${colors.cyan(`v${v24}`)}`)}
89+
if (v22) {console.log(colors.magenta('║') + ` Node 22: ${colors.cyan(`v${v22}`)}`)}
90+
if (v20) {console.log(colors.magenta('║') + ` Node 20: ${colors.cyan(`v${v20}`)}`)}
9191
console.log(colors.magenta('═'.repeat(70)) + '\n')
9292
}
9393

scripts/build/build-stub.mjs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,12 @@
66
* yao-pkg with custom Node.js builds.
77
*/
88

9-
import { spawn, execSync } from 'node:child_process'
9+
import { execSync, spawn } from 'node:child_process'
1010
import { existsSync, readFileSync, readdirSync } from 'node:fs'
11-
import { mkdir, writeFile, copyFile, stat, unlink, rename } from 'node:fs/promises'
11+
import { copyFile, mkdir, rename, stat, unlink, writeFile } from 'node:fs/promises'
12+
import { homedir, arch as osArch, platform as osPlatform, tmpdir } from 'node:os'
1213
import { dirname, join, resolve } from 'node:path'
13-
import { tmpdir } from 'node:os'
1414
import { fileURLToPath } from 'node:url'
15-
import { platform as osPlatform, arch as osArch, homedir } from 'node:os'
1615

1716
import colors from 'yoctocolors-cjs'
1817

@@ -350,7 +349,7 @@ export async function buildStub(options = {}) {
350349

351350
// Step 1: Sync yao-pkg patches if needed (force sync with --sync-yao-patches)
352351
if (syncYaoPatches) {
353-
if (!quiet) console.log('🔄 Syncing yao-pkg patches from upstream...')
352+
if (!quiet) {console.log('🔄 Syncing yao-pkg patches from upstream...')}
354353
await fetchYaoPatches({ quiet })
355354
}
356355

@@ -580,7 +579,7 @@ export async function buildStub(options = {}) {
580579
return
581580
}
582581
}
583-
if (!quiet) process.stderr.write(data)
582+
if (!quiet) {process.stderr.write(data)}
584583
})
585584
}
586585
}

src/utils/README.md

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
# Utils Directory Organization Guide
2+
3+
## Directory Structure
4+
5+
The utils directory contains shared utilities used across the Socket CLI. To reduce cognitive load, utilities are organized by their primary function:
6+
7+
### API & Network (`api-*.mts`, `http.mts`)
8+
- `api.mts` - Main API client and request handling
9+
- `api-types.mts` - TypeScript types for API responses
10+
- `api-wrapper.mts` - High-level API wrapper functions
11+
- `http.mts` - HTTP utilities and helpers
12+
13+
### Command & CLI (`cmd-*.mts`, `meow-*.mts`)
14+
- `cmd.mts` - Command execution utilities
15+
- `command-builder.mts` - Build command structures
16+
- `command-logger.mts` - Log command execution
17+
- `meow-with-subcommands.mts` - Meow CLI framework extensions
18+
19+
### Error Handling (`error-*.mts`, `fail-*.mts`)
20+
- `errors.mts` - Error type definitions
21+
- `error-display.mts` - Format errors for display
22+
- `error-filter.mts` - Filter and categorize errors
23+
- `error-handler.mts` - Central error handling
24+
- `fail-msg-with-badge.mts` - Format failure messages
25+
- `result.mts` - Result/Either pattern implementation
26+
27+
### Output & Formatting (`output*.mts`, `*format*.mts`, `color*.mts`)
28+
- `output.mts` - Main output handler
29+
- `output-formatting.mts` - Format output for different modes
30+
- `simple-output.mts` - Simplified output helpers
31+
- `color-or-markdown.mts` - Choose between colored or markdown output
32+
- `markdown.mts` - Markdown formatting utilities
33+
34+
### File System (`fs.mts`, `glob.mts`, `path*.mts`)
35+
- `fs.mts` - File system operations
36+
- `glob.mts` - File globbing utilities
37+
- `path-resolve.mts` - Path resolution helpers
38+
39+
### Package Management (`package-*.mts`, `npm-*.mts`, `pnpm.mts`)
40+
- `package-manager.mts` - Detect and use package managers
41+
- `package-environment.mts` - Package environment detection
42+
- `npm-config.mts` - NPM configuration utilities
43+
- `pnpm.mts` - PNPM-specific utilities
44+
45+
### Process & Execution (`process-*.mts`, `spawn.mts`)
46+
- `process-runner.mts` - Run processes with retries
47+
- `spawn.mts` - Spawn child processes
48+
- `coana-spawn.mts` - Spawn Coana processes
49+
- `shadow-runner.mts` - Run shadow binaries
50+
51+
### Git & Version Control (`git*.mts`)
52+
- `git.mts` - Git operations
53+
- `git-url.mts` - Parse and build git URLs
54+
- `github.mts` - GitHub API utilities
55+
56+
### Security & Validation (`socket-*.mts`, `purl*.mts`)
57+
- `socket-package-alert.mts` - Package security alerts
58+
- `purl.mts` - Package URL (PURL) utilities
59+
- `purl-to-ghsa.mts` - Convert PURLs to GitHub Security Advisories
60+
61+
### Configuration (`config*.mts`, `filter-*.mts`)
62+
- `config.mts` - Main configuration loader
63+
- `filter-config.mts` - Filter configuration options
64+
- `registry.mts` - Package registry utilities
65+
66+
### Interactive & UI (`ink*.mts`, `bordered-*.mts`, `ask-*.mts`)
67+
- `ink.mts` - Ink React components
68+
- `bordered-input.mts` - Bordered input components
69+
- `ask-mode.mts` - Interactive prompt mode
70+
71+
### Update & Version Management (`update-*.mts`)
72+
- `update-checker.mts` - Check for CLI updates
73+
- `update-manager.mts` - Manage CLI updates
74+
75+
### Caching (`cache-*.mts`)
76+
- `cache-strategies.mts` - Different caching strategies
77+
78+
### Utilities & Helpers
79+
- `alerts-map.mts` - Map alert types to display
80+
- `check-input.mts` - Validate user input
81+
- `constants-runtime.mts` - Runtime constants
82+
- `debug.mts` - Debug utilities
83+
- `dlx-*.mts` - DLX (package runner) utilities
84+
- `log.mts` - Logging utilities
85+
- `objects.mts` - Object manipulation utilities
86+
- `normalize-options.mts` - Normalize command options
87+
- `requirements.mts` - API requirements configuration
88+
- `sdk.mts` - Socket SDK utilities
89+
- `serialize-*.mts` - Serialization utilities
90+
- `translations.mts` - Alert translations
91+
- `visitor.mts` - AST visitor pattern utilities
92+
93+
## Best Practices
94+
95+
1. **Group imports** - Import related utilities together
96+
2. **Use specific imports** - Import only what you need
97+
3. **Avoid circular dependencies** - Check imports carefully
98+
4. **Keep utilities focused** - Each file should have a single responsibility
99+
5. **Document exports** - Use JSDoc for public functions
100+
101+
## Common Patterns
102+
103+
### Error Handling
104+
```typescript
105+
import { InputError, AuthError } from './utils/errors.mts'
106+
import { outputError } from './utils/error-display.mts'
107+
```
108+
109+
### Output Formatting
110+
```typescript
111+
import { outputResult } from './utils/output.mts'
112+
import { formatMarkdown } from './utils/markdown.mts'
113+
```
114+
115+
### API Calls
116+
```typescript
117+
import { setupSdk } from './utils/sdk.mts'
118+
import { apiWrapper } from './utils/api-wrapper.mts'
119+
```

0 commit comments

Comments
 (0)