@portel/photon 1.1.0 → 1.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.
Files changed (44) hide show
  1. package/README.md +279 -65
  2. package/dist/cli-alias.d.ts +21 -0
  3. package/dist/cli-alias.d.ts.map +1 -0
  4. package/dist/cli-alias.js +227 -0
  5. package/dist/cli-alias.js.map +1 -0
  6. package/dist/cli.js +262 -135
  7. package/dist/cli.js.map +1 -1
  8. package/dist/daemon/client.d.ts +15 -0
  9. package/dist/daemon/client.d.ts.map +1 -0
  10. package/dist/daemon/client.js +126 -0
  11. package/dist/daemon/client.js.map +1 -0
  12. package/dist/daemon/manager.d.ts +32 -0
  13. package/dist/daemon/manager.d.ts.map +1 -0
  14. package/dist/daemon/manager.js +155 -0
  15. package/dist/daemon/manager.js.map +1 -0
  16. package/dist/daemon/protocol.d.ts +48 -0
  17. package/dist/daemon/protocol.d.ts.map +1 -0
  18. package/dist/daemon/protocol.js +7 -0
  19. package/dist/daemon/protocol.js.map +1 -0
  20. package/dist/daemon/server.d.ts +12 -0
  21. package/dist/daemon/server.d.ts.map +1 -0
  22. package/dist/daemon/server.js +215 -0
  23. package/dist/daemon/server.js.map +1 -0
  24. package/dist/daemon/session-manager.d.ts +46 -0
  25. package/dist/daemon/session-manager.d.ts.map +1 -0
  26. package/dist/daemon/session-manager.js +120 -0
  27. package/dist/daemon/session-manager.js.map +1 -0
  28. package/dist/photon-cli-runner.d.ts +15 -0
  29. package/dist/photon-cli-runner.d.ts.map +1 -0
  30. package/dist/photon-cli-runner.js +791 -0
  31. package/dist/photon-cli-runner.js.map +1 -0
  32. package/dist/photon-doc-extractor.d.ts +10 -0
  33. package/dist/photon-doc-extractor.d.ts.map +1 -1
  34. package/dist/photon-doc-extractor.js +88 -8
  35. package/dist/photon-doc-extractor.js.map +1 -1
  36. package/dist/schema-extractor.d.ts +27 -0
  37. package/dist/schema-extractor.d.ts.map +1 -1
  38. package/dist/schema-extractor.js +333 -2
  39. package/dist/schema-extractor.js.map +1 -1
  40. package/dist/template-manager.js +1 -1
  41. package/dist/types.d.ts +1 -0
  42. package/dist/types.d.ts.map +1 -1
  43. package/dist/types.js.map +1 -1
  44. package/package.json +5 -4
package/README.md CHANGED
@@ -13,6 +13,27 @@ Photon TS files are Single file. Zero boilerplate. Pure business logic.
13
13
 
14
14
  ---
15
15
 
16
+ ## TL;DR
17
+
18
+ **The Problem with MCPs Today:**
19
+
20
+ - Popular MCPs don't exactly match your specific requirements
21
+ - **Security risk**: Malicious MCPs can steal your data through prompt injection—not just credentials
22
+ - Scattered across 4-6 files, making security audits impractical
23
+ - Too complex to fork and customize safely
24
+
25
+ **Photon's Solution:** Single-file TypeScript format. Pure business logic, zero boilerplate. Fork-first design where every `.photon.ts` is trivial to audit and customize.
26
+
27
+ Think of it like **NPM and Node, but for MCP**.
28
+
29
+ ### The Photon Ecosystem Flywheel
30
+
31
+ ![Photon Ecosystem](https://raw.githubusercontent.com/portel-dev/photon/refs/heads/main/assets/photon-ecosystem.png)
32
+
33
+ The ecosystem creates a virtuous cycle: AI generates photons → Runtime executes them → Community shares → AI gets smarter.
34
+
35
+ ---
36
+
16
37
  ## The Problem
17
38
 
18
39
  Traditional MCP servers scatter your logic across 4-6 files:
@@ -118,11 +139,25 @@ photon mcp my-jira # Works immediately
118
139
  ```
119
140
 
120
141
  **Use cases:**
142
+
121
143
  - Add company-specific authentication
122
144
  - Customize business logic
123
145
  - Merge multiple photons
124
146
  - Experiment without breaking originals
125
147
 
148
+ ### 🔒 Security Through Transparency
149
+
150
+ Prompt injection attacks are the new supply-chain threat. A malicious MCP can manipulate AI responses to exfiltrate your entire conversation history—not just credentials.
151
+
152
+ **One file = one audit:**
153
+
154
+ - Read 40 lines, understand everything
155
+ - No hidden code scattered across imports
156
+ - Fork and verify in minutes, not hours
157
+ - Trust through transparency, not reputation
158
+
159
+ When you can't trust a photon, you can **safely fork and audit it**. Traditional MCPs with scattered logic? Nearly impossible to verify.
160
+
126
161
  ### 📦 Zero-Friction Dependencies
127
162
 
128
163
  Dependencies are auto-installed via JSDoc (like `npx` or `uv`):
@@ -151,13 +186,32 @@ The [**official Photon marketplace**](https://github.com/portel-dev/photons) com
151
186
 
152
187
  ```bash
153
188
  # Browse all photons
154
- photon get
189
+ photon info
155
190
 
156
191
  # Install any photon (filesystem, git, postgres, mongodb, slack, etc.)
157
192
  photon add filesystem
158
193
 
159
- # Run as MCP server
160
- photon mcp filesystem
194
+ # or else copy your own .photon.ts file to
195
+ # .photon folder in your user folder
196
+
197
+ # Call info command with mcp option
198
+ photon info filesystem --mcp
199
+ # Get client config json
200
+ {
201
+ "filesystem": {
202
+ "command": "photon",
203
+ "args": [
204
+ "mcp",
205
+ "filesystem"
206
+ ],
207
+ "env": {
208
+ "FILESYSTEM_WORKDIR": "/Users/arul/Documents",
209
+ "FILESYSTEM_MAX_FILE_SIZE": "10485760",
210
+ "FILESYSTEM_ALLOW_HIDDEN": "false"
211
+ }
212
+ }
213
+ }
214
+ # Add to your client
161
215
  ```
162
216
 
163
217
  ### Build Photons with AI
@@ -177,17 +231,6 @@ photon marketplace add your-org/your-photons
177
231
  photon add your-custom-tool
178
232
  ```
179
233
 
180
- ### Integrate with Your MCP Client
181
-
182
- ```bash
183
- # Get configuration for any MCP client
184
- photon get filesystem --mcp
185
- ```
186
-
187
- Add the output to your MCP client's config file. **Consult your client's documentation** for setup instructions.
188
-
189
- **MCP clients include:** Claude Desktop, Cursor, Zed, Continue, Cline, and more.
190
-
191
234
  ---
192
235
 
193
236
  ## The Value Proposition
@@ -202,11 +245,172 @@ Add the output to your MCP client's config file. **Consult your client's documen
202
245
  | **Dependencies** | Manual npm install | Auto-installed from @dependencies |
203
246
  | **Hot Reload** | Configure yourself | Built-in with --dev |
204
247
  | **AI Context** | Scattered | Single file |
248
+ | **CLI Interface** | Write separate code | Automatic from same code |
205
249
 
206
250
  [See detailed comparison →](COMPARISON.md)
207
251
 
208
252
  ---
209
253
 
254
+ ## CLI Interface
255
+
256
+ Every photon automatically provides a beautiful CLI interface with zero additional code. The same business logic that powers your MCP tools becomes instantly available from the terminal.
257
+
258
+ ### Quick Example
259
+
260
+ ```bash
261
+ # List all methods
262
+ photon cli lg-remote
263
+
264
+ # Call methods with natural syntax
265
+ photon cli lg-remote volume 50
266
+ photon cli lg-remote volume +5
267
+ photon cli lg-remote channel 7
268
+ photon cli lg-remote app netflix
269
+
270
+ # Get method help
271
+ photon cli lg-remote volume --help
272
+ ```
273
+
274
+ ### Beautiful Output Formats
275
+
276
+ Photon automatically formats output based on data structure:
277
+
278
+ **Tables** - Key-value pairs and flat objects:
279
+ ```bash
280
+ $ photon cli lg-remote volume
281
+ ┌─────────┬────┐
282
+ │ volume │ 45 │
283
+ ├─────────┼────┤
284
+ │ muted │ no │
285
+ ├─────────┼────┤
286
+ │ maxVol │ 100│
287
+ └─────────┴────┘
288
+ ```
289
+
290
+ **Lists** - Arrays of items:
291
+ ```bash
292
+ $ photon cli lg-remote apps
293
+ • Netflix (netflix)
294
+ • YouTube (youtube.leanback.v4)
295
+ • HDMI1 (com.webos.app.hdmi1)
296
+ • Disney+ (disney)
297
+ ```
298
+
299
+ **Trees** - Hierarchical data (shown as formatted JSON)
300
+ **Primitives** - Simple values displayed directly
301
+
302
+ ### Format System
303
+
304
+ Photon uses a smart format system with 5 standard types:
305
+
306
+ 1. **`primitive`** - String, number, boolean
307
+ 2. **`table`** - Flat object or array of flat objects
308
+ 3. **`tree`** - Nested/hierarchical data
309
+ 4. **`list`** - Array of simple items
310
+ 5. **`none`** - No return value (void operations)
311
+
312
+ **Hint the format** (optional):
313
+ ```typescript
314
+ /**
315
+ * Get current volume
316
+ * @format table
317
+ */
318
+ async volume() {
319
+ return this._request('ssap://audio/getVolume');
320
+ }
321
+ ```
322
+
323
+ **Auto-detection**: If no `@format` tag is provided, Photon automatically detects the best format based on the return value structure.
324
+
325
+ ### CLI Command Reference
326
+
327
+ #### `photon cli <photon-name> [method] [args...]`
328
+
329
+ **List all methods:**
330
+ ```bash
331
+ photon cli lg-remote
332
+ ```
333
+
334
+ **Call a method:**
335
+ ```bash
336
+ # No parameters
337
+ photon cli lg-remote status
338
+
339
+ # Single parameter
340
+ photon cli lg-remote volume 50
341
+
342
+ # Multiple parameters
343
+ photon cli lg-remote search query "breaking bad" limit 10
344
+
345
+ # Relative adjustments
346
+ photon cli lg-remote volume +5
347
+ photon cli lg-remote channel +1
348
+ ```
349
+
350
+ **Get method help:**
351
+ ```bash
352
+ photon cli lg-remote volume --help
353
+ ```
354
+
355
+ **Raw JSON output:**
356
+ ```bash
357
+ photon cli lg-remote volume --json
358
+ ```
359
+
360
+ ### One Codebase, Multiple Interfaces
361
+
362
+ The beauty of Photon's design: **improvements to business logic automatically work across all interfaces**.
363
+
364
+ Write your logic once:
365
+ ```typescript
366
+ async volume(params?: { level?: number | string } | number | string) {
367
+ // Handle relative adjustments
368
+ if (typeof level === 'string' && level.startsWith('+')) {
369
+ const delta = parseInt(level);
370
+ const current = await this._getCurrentVolume();
371
+ const newVolume = current + delta;
372
+ await this._setVolume(newVolume);
373
+ }
374
+ // ... rest of logic
375
+ return this._getCurrentVolume(); // Always return current state
376
+ }
377
+ ```
378
+
379
+ **Works everywhere:**
380
+ - ✅ **MCP**: Claude Desktop, Cursor, etc.
381
+ - ✅ **CLI**: `photon cli lg-remote volume +5`
382
+ - ✅ **Future interfaces**: HTTP, WebSocket, etc.
383
+
384
+ ### Context-Aware Error Messages
385
+
386
+ Photons can provide helpful, context-aware errors:
387
+
388
+ ```bash
389
+ $ photon cli lg-remote channels
390
+ ❌ Error: TV channels not available. Currently on HDMI1.
391
+ Switch to a TV tuner input to access channels.
392
+ ```
393
+
394
+ The same error quality appears in MCP tools—because it's the same code.
395
+
396
+ ### Exit Codes
397
+
398
+ The CLI properly returns exit codes for automation:
399
+ - **0**: Success
400
+ - **1**: Error (tool execution failed, invalid parameters, etc.)
401
+
402
+ Perfect for shell scripts and CI/CD:
403
+ ```bash
404
+ if photon cli lg-remote volume 50; then
405
+ echo "Volume set successfully"
406
+ else
407
+ echo "Failed to set volume"
408
+ exit 1
409
+ fi
410
+ ```
411
+
412
+ ---
413
+
210
414
  ## How Photon Works
211
415
 
212
416
  ### Convention = Automation
@@ -270,7 +474,7 @@ Production-ready photons from **[portel-dev/photons](https://github.com/portel-d
270
474
 
271
475
  Browse and install:
272
476
  ```bash
273
- photon get # See all available photons
477
+ photon info # See all available photons
274
478
  photon add postgres # Install any photon
275
479
  photon search git # Search by keyword
276
480
  ```
@@ -420,20 +624,69 @@ photon mcp calculator --config
420
624
  - `--validate` - Validate configuration without running server
421
625
  - `--config` - Show configuration template and exit
422
626
 
627
+ #### `photon cli <photon-name> [method] [args...]`
628
+ Run photon methods directly from the command line.
629
+
630
+ ```bash
631
+ # List all available methods
632
+ photon cli calculator
633
+
634
+ # Call a method with arguments
635
+ photon cli calculator add 5 10
636
+
637
+ # Get method-specific help
638
+ photon cli calculator add --help
639
+
640
+ # Output raw JSON instead of formatted output
641
+ photon cli calculator add 5 10 --json
642
+ ```
643
+
644
+ **Arguments:**
645
+ - Arguments are automatically coerced to expected types (string, number, boolean)
646
+ - Strings starting with `+` or `-` are preserved for relative adjustments
647
+ - Arrays and objects can be passed as JSON strings
648
+
649
+ **Options:**
650
+ - `--help` - Show help for the photon or specific method
651
+ - `--json` - Output raw JSON instead of formatted output
652
+
653
+ **Exit Codes:**
654
+ - `0` - Success
655
+ - `1` - Error (invalid arguments, execution failure, etc.)
656
+
657
+ **Examples:**
658
+
659
+ ```bash
660
+ # Smart home control
661
+ photon cli lg-remote volume 50
662
+ photon cli lg-remote volume +5 # Relative adjustment
663
+ photon cli lg-remote channel 7
664
+ photon cli lg-remote app netflix
665
+
666
+ # Database queries
667
+ photon cli postgres query "SELECT * FROM users LIMIT 10"
668
+
669
+ # File operations
670
+ photon cli filesystem read-file path "/home/user/document.txt"
671
+
672
+ # Git operations
673
+ photon cli git commit message "feat: add new feature"
674
+ ```
675
+
423
676
  ### Inspect & Configure
424
677
 
425
- #### `photon get [name]`
678
+ #### `photon info [name]`
426
679
  List all photons or show details for a specific one.
427
680
 
428
681
  ```bash
429
682
  # List all installed photons
430
- photon get
683
+ photon info
431
684
 
432
685
  # Show details for one photon
433
- photon get calculator
686
+ photon info calculator
434
687
 
435
688
  # Get MCP client configuration
436
- photon get calculator --mcp
689
+ photon info calculator --mcp
437
690
  ```
438
691
 
439
692
  **Options:**
@@ -868,46 +1121,6 @@ export default class MyPhoton {
868
1121
 
869
1122
  ---
870
1123
 
871
- ## Integration with MCP Clients
872
-
873
- Photon works with **any MCP client**:
874
-
875
- - **Claude Desktop** (Anthropic)
876
- - **Cursor** (IDE)
877
- - **Zed** (IDE)
878
- - **Continue** (VS Code extension)
879
- - **Cline** (VS Code extension)
880
- - ... and more
881
-
882
- ### Setup
883
-
884
- ```bash
885
- # Get configuration for your MCP client
886
- photon get <photon-name> --mcp
887
- ```
888
-
889
- **Consult your MCP client's documentation** for:
890
- - Config file location
891
- - Configuration format
892
- - Setup instructions
893
-
894
- Example output:
895
- ```json
896
- {
897
- "analytics": {
898
- "command": "photon",
899
- "args": ["mcp", "analytics"],
900
- "env": {
901
- "ANALYTICS_HOST": "localhost",
902
- "ANALYTICS_DATABASE": "company",
903
- "ANALYTICS_PASSWORD": "secret"
904
- }
905
- }
906
- }
907
- ```
908
-
909
- ---
910
-
911
1124
  ## Examples
912
1125
 
913
1126
  The repository includes example photons in `examples/`:
@@ -1029,18 +1242,19 @@ photon upgrade <name> # Update specific photon
1029
1242
 
1030
1243
  ## Roadmap
1031
1244
 
1032
- ### ✅ Version 1.0 - MCP Servers (Available Now)
1245
+ ### ✅ MCP Servers & CLI Interface (Available Now)
1033
1246
 
1247
+ **MCP Servers:**
1034
1248
  Build and run photons as MCP servers for AI assistants. Works with Claude Desktop, Cursor, Zed, Continue, Cline, and any MCP-compatible client.
1035
1249
 
1036
- ### 🔮 Future Versions
1250
+ **CLI Interface:**
1251
+ Run photon methods directly from the command line with beautiful formatted output. Every photon automatically becomes a CLI tool with zero additional code.
1037
1252
 
1038
- Photon's framework-agnostic design enables future deployment targets:
1253
+ **Write once, deploy everywhere:** The same business logic powers both your MCP tools and CLI commands.
1039
1254
 
1040
- - **CLI tools** - Run photons as terminal commands
1041
- - **More targets** - Additional deployment options as the ecosystem grows
1255
+ ---
1042
1256
 
1043
- **The vision:** Write focused business logic once. As Photon evolves, deploy it to multiple targets.
1257
+ Photon's framework-agnostic design enables future deployment targets. More on the way.
1044
1258
 
1045
1259
  ---
1046
1260
 
@@ -0,0 +1,21 @@
1
+ /**
2
+ * CLI Alias Manager (Cross-Platform)
3
+ *
4
+ * Creates executable aliases for photons so they can be called directly
5
+ * Supports: Windows, macOS, Linux
6
+ * Example: Instead of `photon cli lg-remote discover`
7
+ * Run: `lg-remote discover`
8
+ */
9
+ /**
10
+ * Create a CLI alias for a photon (cross-platform)
11
+ */
12
+ export declare function createAlias(photonName: string, aliasName?: string): Promise<void>;
13
+ /**
14
+ * Remove a CLI alias (cross-platform)
15
+ */
16
+ export declare function removeAlias(aliasName: string): Promise<void>;
17
+ /**
18
+ * List all CLI aliases (cross-platform)
19
+ */
20
+ export declare function listAliases(): Promise<void>;
21
+ //# sourceMappingURL=cli-alias.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-alias.d.ts","sourceRoot":"","sources":["../src/cli-alias.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAYH;;GAEG;AACH,wBAAsB,WAAW,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAsCvF;AAoFD;;GAEG;AACH,wBAAsB,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAyBlE;AAED;;GAEG;AACH,wBAAsB,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CA+CjD"}
@@ -0,0 +1,227 @@
1
+ /**
2
+ * CLI Alias Manager (Cross-Platform)
3
+ *
4
+ * Creates executable aliases for photons so they can be called directly
5
+ * Supports: Windows, macOS, Linux
6
+ * Example: Instead of `photon cli lg-remote discover`
7
+ * Run: `lg-remote discover`
8
+ */
9
+ import * as fs from 'fs/promises';
10
+ import * as path from 'path';
11
+ import * as os from 'os';
12
+ import { existsSync } from 'fs';
13
+ import { resolvePhotonPath } from './path-resolver.js';
14
+ const ALIAS_DIR = path.join(os.homedir(), '.photon', 'bin');
15
+ const IS_WINDOWS = process.platform === 'win32';
16
+ const PATH_SEPARATOR = IS_WINDOWS ? ';' : ':';
17
+ /**
18
+ * Create a CLI alias for a photon (cross-platform)
19
+ */
20
+ export async function createAlias(photonName, aliasName) {
21
+ try {
22
+ // Verify photon exists
23
+ const photonPath = await resolvePhotonPath(photonName);
24
+ if (!photonPath) {
25
+ console.error(`❌ Photon '${photonName}' not found`);
26
+ console.error(`\nInstall it first with: photon add ${photonName}`);
27
+ process.exit(1);
28
+ }
29
+ // Use provided alias name or default to photon name
30
+ const cmdName = aliasName || photonName;
31
+ // Create bin directory if it doesn't exist
32
+ await fs.mkdir(ALIAS_DIR, { recursive: true });
33
+ // Determine which photon executable to use
34
+ const photonCmd = await findPhotonExecutable();
35
+ // Create platform-specific alias file
36
+ if (IS_WINDOWS) {
37
+ await createWindowsAlias(cmdName, photonName, photonCmd);
38
+ }
39
+ else {
40
+ await createUnixAlias(cmdName, photonName, photonCmd);
41
+ }
42
+ console.log(`✅ Created alias: ${cmdName}`);
43
+ console.log(`\nYou can now run:`);
44
+ console.log(` ${cmdName} <command> [options]`);
45
+ console.log(`\nInstead of:`);
46
+ console.log(` photon cli ${photonName} <command> [options]`);
47
+ // Check if bin directory is in PATH and provide instructions
48
+ await checkAndInstructPath();
49
+ }
50
+ catch (error) {
51
+ console.error(`❌ Error: ${error.message}`);
52
+ process.exit(1);
53
+ }
54
+ }
55
+ /**
56
+ * Create Unix-style alias (bash script)
57
+ */
58
+ async function createUnixAlias(cmdName, photonName, photonCmd) {
59
+ const aliasPath = path.join(ALIAS_DIR, cmdName);
60
+ // Check if alias already exists
61
+ if (existsSync(aliasPath)) {
62
+ console.error(`⚠️ Alias '${cmdName}' already exists`);
63
+ console.error(`\nRemove it first with: photon unalias ${cmdName}`);
64
+ process.exit(1);
65
+ }
66
+ const script = `#!/bin/bash
67
+ # Auto-generated alias for photon: ${photonName}
68
+ ${photonCmd} cli ${photonName} "$@"
69
+ `;
70
+ await fs.writeFile(aliasPath, script, { mode: 0o755 });
71
+ }
72
+ /**
73
+ * Create Windows-style alias (batch file)
74
+ */
75
+ async function createWindowsAlias(cmdName, photonName, photonCmd) {
76
+ const aliasPath = path.join(ALIAS_DIR, `${cmdName}.cmd`);
77
+ // Check if alias already exists
78
+ if (existsSync(aliasPath)) {
79
+ console.error(`⚠️ Alias '${cmdName}' already exists`);
80
+ console.error(`\nRemove it first with: photon unalias ${cmdName}`);
81
+ process.exit(1);
82
+ }
83
+ const script = `@echo off
84
+ REM Auto-generated alias for photon: ${photonName}
85
+ ${photonCmd} cli ${photonName} %*
86
+ `;
87
+ await fs.writeFile(aliasPath, script);
88
+ }
89
+ /**
90
+ * Check if alias directory is in PATH and provide platform-specific instructions
91
+ */
92
+ async function checkAndInstructPath() {
93
+ const pathEnv = process.env.PATH || '';
94
+ const paths = pathEnv.split(PATH_SEPARATOR);
95
+ if (paths.includes(ALIAS_DIR)) {
96
+ // Already in PATH
97
+ return;
98
+ }
99
+ console.log(`\n⚠️ ${ALIAS_DIR} is not in your PATH`);
100
+ if (IS_WINDOWS) {
101
+ console.log(`\nTo add it permanently, run this in PowerShell (as Administrator):`);
102
+ console.log(` [Environment]::SetEnvironmentVariable("Path", $env:Path + ";${ALIAS_DIR}", "User")`);
103
+ console.log(`\nOr add it manually:`);
104
+ console.log(` 1. Open "Environment Variables" in Windows settings`);
105
+ console.log(` 2. Edit the "Path" variable for your user`);
106
+ console.log(` 3. Add: ${ALIAS_DIR}`);
107
+ console.log(` 4. Restart your terminal`);
108
+ }
109
+ else {
110
+ // Detect shell
111
+ const shell = process.env.SHELL || '';
112
+ let configFile = '~/.bashrc';
113
+ if (shell.includes('zsh')) {
114
+ configFile = '~/.zshrc';
115
+ }
116
+ else if (shell.includes('fish')) {
117
+ configFile = '~/.config/fish/config.fish';
118
+ }
119
+ console.log(`\nAdd this to your ${configFile}:`);
120
+ console.log(` export PATH="$PATH:${ALIAS_DIR}"`);
121
+ console.log(`\nThen reload your shell:`);
122
+ console.log(` source ${configFile}`);
123
+ }
124
+ }
125
+ /**
126
+ * Remove a CLI alias (cross-platform)
127
+ */
128
+ export async function removeAlias(aliasName) {
129
+ try {
130
+ // Try both Unix and Windows formats
131
+ const unixPath = path.join(ALIAS_DIR, aliasName);
132
+ const windowsPath = path.join(ALIAS_DIR, `${aliasName}.cmd`);
133
+ let aliasPath = null;
134
+ if (existsSync(unixPath)) {
135
+ aliasPath = unixPath;
136
+ }
137
+ else if (existsSync(windowsPath)) {
138
+ aliasPath = windowsPath;
139
+ }
140
+ if (!aliasPath) {
141
+ console.error(`❌ Alias '${aliasName}' not found`);
142
+ process.exit(1);
143
+ }
144
+ await fs.unlink(aliasPath);
145
+ console.log(`✅ Removed alias: ${aliasName}`);
146
+ }
147
+ catch (error) {
148
+ console.error(`❌ Error: ${error.message}`);
149
+ process.exit(1);
150
+ }
151
+ }
152
+ /**
153
+ * List all CLI aliases (cross-platform)
154
+ */
155
+ export async function listAliases() {
156
+ try {
157
+ if (!existsSync(ALIAS_DIR)) {
158
+ console.log('No aliases created yet.');
159
+ console.log(`\nCreate one with: photon alias <photon-name>`);
160
+ return;
161
+ }
162
+ const files = await fs.readdir(ALIAS_DIR);
163
+ if (files.length === 0) {
164
+ console.log('No aliases created yet.');
165
+ console.log(`\nCreate one with: photon alias <photon-name>`);
166
+ return;
167
+ }
168
+ console.log(`\nCLI Aliases (${ALIAS_DIR}):\n`);
169
+ for (const file of files) {
170
+ const aliasPath = path.join(ALIAS_DIR, file);
171
+ const stat = await fs.stat(aliasPath);
172
+ if (stat.isFile()) {
173
+ // Read the script to find which photon it points to
174
+ const content = await fs.readFile(aliasPath, 'utf-8');
175
+ const match = content.match(/photon cli (\S+)/);
176
+ const photonName = match ? match[1] : 'unknown';
177
+ // Display name without .cmd extension on Windows
178
+ const displayName = file.replace(/\.cmd$/, '');
179
+ console.log(` ${displayName} → photon cli ${photonName}`);
180
+ }
181
+ }
182
+ console.log('');
183
+ // Check if bin directory is in PATH
184
+ const pathEnv = process.env.PATH || '';
185
+ const paths = pathEnv.split(PATH_SEPARATOR);
186
+ if (!paths.includes(ALIAS_DIR)) {
187
+ await checkAndInstructPath();
188
+ }
189
+ }
190
+ catch (error) {
191
+ console.error(`❌ Error: ${error.message}`);
192
+ process.exit(1);
193
+ }
194
+ }
195
+ /**
196
+ * Find the photon executable path
197
+ */
198
+ async function findPhotonExecutable() {
199
+ // Check if running from global installation
200
+ const globalPhoton = await findInPath('photon');
201
+ if (globalPhoton) {
202
+ return globalPhoton;
203
+ }
204
+ // Fallback to npx
205
+ return 'npx @portel/photon';
206
+ }
207
+ /**
208
+ * Find a command in PATH
209
+ */
210
+ async function findInPath(cmd) {
211
+ const pathEnv = process.env.PATH || '';
212
+ const paths = pathEnv.split(':');
213
+ for (const dir of paths) {
214
+ const fullPath = path.join(dir, cmd);
215
+ if (existsSync(fullPath)) {
216
+ try {
217
+ await fs.access(fullPath, fs.constants.X_OK);
218
+ return fullPath;
219
+ }
220
+ catch {
221
+ continue;
222
+ }
223
+ }
224
+ }
225
+ return null;
226
+ }
227
+ //# sourceMappingURL=cli-alias.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-alias.js","sourceRoot":"","sources":["../src/cli-alias.ts"],"names":[],"mappings":"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"}