@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.
- package/README.md +279 -65
- package/dist/cli-alias.d.ts +21 -0
- package/dist/cli-alias.d.ts.map +1 -0
- package/dist/cli-alias.js +227 -0
- package/dist/cli-alias.js.map +1 -0
- package/dist/cli.js +262 -135
- package/dist/cli.js.map +1 -1
- package/dist/daemon/client.d.ts +15 -0
- package/dist/daemon/client.d.ts.map +1 -0
- package/dist/daemon/client.js +126 -0
- package/dist/daemon/client.js.map +1 -0
- package/dist/daemon/manager.d.ts +32 -0
- package/dist/daemon/manager.d.ts.map +1 -0
- package/dist/daemon/manager.js +155 -0
- package/dist/daemon/manager.js.map +1 -0
- package/dist/daemon/protocol.d.ts +48 -0
- package/dist/daemon/protocol.d.ts.map +1 -0
- package/dist/daemon/protocol.js +7 -0
- package/dist/daemon/protocol.js.map +1 -0
- package/dist/daemon/server.d.ts +12 -0
- package/dist/daemon/server.d.ts.map +1 -0
- package/dist/daemon/server.js +215 -0
- package/dist/daemon/server.js.map +1 -0
- package/dist/daemon/session-manager.d.ts +46 -0
- package/dist/daemon/session-manager.d.ts.map +1 -0
- package/dist/daemon/session-manager.js +120 -0
- package/dist/daemon/session-manager.js.map +1 -0
- package/dist/photon-cli-runner.d.ts +15 -0
- package/dist/photon-cli-runner.d.ts.map +1 -0
- package/dist/photon-cli-runner.js +791 -0
- package/dist/photon-cli-runner.js.map +1 -0
- package/dist/photon-doc-extractor.d.ts +10 -0
- package/dist/photon-doc-extractor.d.ts.map +1 -1
- package/dist/photon-doc-extractor.js +88 -8
- package/dist/photon-doc-extractor.js.map +1 -1
- package/dist/schema-extractor.d.ts +27 -0
- package/dist/schema-extractor.d.ts.map +1 -1
- package/dist/schema-extractor.js +333 -2
- package/dist/schema-extractor.js.map +1 -1
- package/dist/template-manager.js +1 -1
- package/dist/types.d.ts +1 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- 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
|
+

|
|
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
|
|
189
|
+
photon info
|
|
155
190
|
|
|
156
191
|
# Install any photon (filesystem, git, postgres, mongodb, slack, etc.)
|
|
157
192
|
photon add filesystem
|
|
158
193
|
|
|
159
|
-
#
|
|
160
|
-
photon
|
|
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
|
|
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
|
|
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
|
|
683
|
+
photon info
|
|
431
684
|
|
|
432
685
|
# Show details for one photon
|
|
433
|
-
photon
|
|
686
|
+
photon info calculator
|
|
434
687
|
|
|
435
688
|
# Get MCP client configuration
|
|
436
|
-
photon
|
|
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
|
-
### ✅
|
|
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
|
-
|
|
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
|
-
|
|
1253
|
+
**Write once, deploy everywhere:** The same business logic powers both your MCP tools and CLI commands.
|
|
1039
1254
|
|
|
1040
|
-
|
|
1041
|
-
- **More targets** - Additional deployment options as the ecosystem grows
|
|
1255
|
+
---
|
|
1042
1256
|
|
|
1043
|
-
|
|
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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"}
|