@portel/photon 1.2.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 +240 -59
- 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 +75 -1
- 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
|
@@ -139,6 +139,7 @@ photon mcp my-jira # Works immediately
|
|
|
139
139
|
```
|
|
140
140
|
|
|
141
141
|
**Use cases:**
|
|
142
|
+
|
|
142
143
|
- Add company-specific authentication
|
|
143
144
|
- Customize business logic
|
|
144
145
|
- Merge multiple photons
|
|
@@ -149,6 +150,7 @@ photon mcp my-jira # Works immediately
|
|
|
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.
|
|
150
151
|
|
|
151
152
|
**One file = one audit:**
|
|
153
|
+
|
|
152
154
|
- Read 40 lines, understand everything
|
|
153
155
|
- No hidden code scattered across imports
|
|
154
156
|
- Fork and verify in minutes, not hours
|
|
@@ -189,8 +191,27 @@ photon info
|
|
|
189
191
|
# Install any photon (filesystem, git, postgres, mongodb, slack, etc.)
|
|
190
192
|
photon add filesystem
|
|
191
193
|
|
|
192
|
-
#
|
|
193
|
-
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
|
|
194
215
|
```
|
|
195
216
|
|
|
196
217
|
### Build Photons with AI
|
|
@@ -210,17 +231,6 @@ photon marketplace add your-org/your-photons
|
|
|
210
231
|
photon add your-custom-tool
|
|
211
232
|
```
|
|
212
233
|
|
|
213
|
-
### Integrate with Your MCP Client
|
|
214
|
-
|
|
215
|
-
```bash
|
|
216
|
-
# Get configuration for any MCP client
|
|
217
|
-
photon info filesystem --mcp
|
|
218
|
-
```
|
|
219
|
-
|
|
220
|
-
Add the output to your MCP client's config file. **Consult your client's documentation** for setup instructions.
|
|
221
|
-
|
|
222
|
-
**MCP clients include:** Claude Desktop, Cursor, Zed, Continue, Cline, and more.
|
|
223
|
-
|
|
224
234
|
---
|
|
225
235
|
|
|
226
236
|
## The Value Proposition
|
|
@@ -235,11 +245,172 @@ Add the output to your MCP client's config file. **Consult your client's documen
|
|
|
235
245
|
| **Dependencies** | Manual npm install | Auto-installed from @dependencies |
|
|
236
246
|
| **Hot Reload** | Configure yourself | Built-in with --dev |
|
|
237
247
|
| **AI Context** | Scattered | Single file |
|
|
248
|
+
| **CLI Interface** | Write separate code | Automatic from same code |
|
|
238
249
|
|
|
239
250
|
[See detailed comparison →](COMPARISON.md)
|
|
240
251
|
|
|
241
252
|
---
|
|
242
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
|
+
|
|
243
414
|
## How Photon Works
|
|
244
415
|
|
|
245
416
|
### Convention = Automation
|
|
@@ -453,6 +624,55 @@ photon mcp calculator --config
|
|
|
453
624
|
- `--validate` - Validate configuration without running server
|
|
454
625
|
- `--config` - Show configuration template and exit
|
|
455
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
|
+
|
|
456
676
|
### Inspect & Configure
|
|
457
677
|
|
|
458
678
|
#### `photon info [name]`
|
|
@@ -901,46 +1121,6 @@ export default class MyPhoton {
|
|
|
901
1121
|
|
|
902
1122
|
---
|
|
903
1123
|
|
|
904
|
-
## Integration with MCP Clients
|
|
905
|
-
|
|
906
|
-
Photon works with **any MCP client**:
|
|
907
|
-
|
|
908
|
-
- **Claude Desktop** (Anthropic)
|
|
909
|
-
- **Cursor** (IDE)
|
|
910
|
-
- **Zed** (IDE)
|
|
911
|
-
- **Continue** (VS Code extension)
|
|
912
|
-
- **Cline** (VS Code extension)
|
|
913
|
-
- ... and more
|
|
914
|
-
|
|
915
|
-
### Setup
|
|
916
|
-
|
|
917
|
-
```bash
|
|
918
|
-
# Get configuration for your MCP client
|
|
919
|
-
photon info <photon-name> --mcp
|
|
920
|
-
```
|
|
921
|
-
|
|
922
|
-
**Consult your MCP client's documentation** for:
|
|
923
|
-
- Config file location
|
|
924
|
-
- Configuration format
|
|
925
|
-
- Setup instructions
|
|
926
|
-
|
|
927
|
-
Example output:
|
|
928
|
-
```json
|
|
929
|
-
{
|
|
930
|
-
"analytics": {
|
|
931
|
-
"command": "photon",
|
|
932
|
-
"args": ["mcp", "analytics"],
|
|
933
|
-
"env": {
|
|
934
|
-
"ANALYTICS_HOST": "localhost",
|
|
935
|
-
"ANALYTICS_DATABASE": "company",
|
|
936
|
-
"ANALYTICS_PASSWORD": "secret"
|
|
937
|
-
}
|
|
938
|
-
}
|
|
939
|
-
}
|
|
940
|
-
```
|
|
941
|
-
|
|
942
|
-
---
|
|
943
|
-
|
|
944
1124
|
## Examples
|
|
945
1125
|
|
|
946
1126
|
The repository includes example photons in `examples/`:
|
|
@@ -1062,18 +1242,19 @@ photon upgrade <name> # Update specific photon
|
|
|
1062
1242
|
|
|
1063
1243
|
## Roadmap
|
|
1064
1244
|
|
|
1065
|
-
### ✅
|
|
1245
|
+
### ✅ MCP Servers & CLI Interface (Available Now)
|
|
1066
1246
|
|
|
1247
|
+
**MCP Servers:**
|
|
1067
1248
|
Build and run photons as MCP servers for AI assistants. Works with Claude Desktop, Cursor, Zed, Continue, Cline, and any MCP-compatible client.
|
|
1068
1249
|
|
|
1069
|
-
|
|
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.
|
|
1070
1252
|
|
|
1071
|
-
|
|
1253
|
+
**Write once, deploy everywhere:** The same business logic powers both your MCP tools and CLI commands.
|
|
1072
1254
|
|
|
1073
|
-
|
|
1074
|
-
- **More targets** - Additional deployment options as the ecosystem grows
|
|
1255
|
+
---
|
|
1075
1256
|
|
|
1076
|
-
|
|
1257
|
+
Photon's framework-agnostic design enables future deployment targets. More on the way.
|
|
1077
1258
|
|
|
1078
1259
|
---
|
|
1079
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":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,MAAM,aAAa,CAAC;AAClC,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAChC,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAEvD,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,KAAK,CAAC,CAAC;AAC5D,MAAM,UAAU,GAAG,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC;AAChD,MAAM,cAAc,GAAG,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;AAE9C;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,UAAkB,EAAE,SAAkB;IACtE,IAAI,CAAC;QACH,uBAAuB;QACvB,MAAM,UAAU,GAAG,MAAM,iBAAiB,CAAC,UAAU,CAAC,CAAC;QACvD,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,OAAO,CAAC,KAAK,CAAC,aAAa,UAAU,aAAa,CAAC,CAAC;YACpD,OAAO,CAAC,KAAK,CAAC,uCAAuC,UAAU,EAAE,CAAC,CAAC;YACnE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,oDAAoD;QACpD,MAAM,OAAO,GAAG,SAAS,IAAI,UAAU,CAAC;QAExC,2CAA2C;QAC3C,MAAM,EAAE,CAAC,KAAK,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAE/C,2CAA2C;QAC3C,MAAM,SAAS,GAAG,MAAM,oBAAoB,EAAE,CAAC;QAE/C,sCAAsC;QACtC,IAAI,UAAU,EAAE,CAAC;YACf,MAAM,kBAAkB,CAAC,OAAO,EAAE,UAAU,EAAE,SAAS,CAAC,CAAC;QAC3D,CAAC;aAAM,CAAC;YACN,MAAM,eAAe,CAAC,OAAO,EAAE,UAAU,EAAE,SAAS,CAAC,CAAC;QACxD,CAAC;QAED,OAAO,CAAC,GAAG,CAAC,oBAAoB,OAAO,EAAE,CAAC,CAAC;QAC3C,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;QAClC,OAAO,CAAC,GAAG,CAAC,OAAO,OAAO,sBAAsB,CAAC,CAAC;QAClD,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;QAC7B,OAAO,CAAC,GAAG,CAAC,kBAAkB,UAAU,sBAAsB,CAAC,CAAC;QAEhE,6DAA6D;QAC7D,MAAM,oBAAoB,EAAE,CAAC;IAC/B,CAAC;IAAC,OAAO,KAAU,EAAE,CAAC;QACpB,OAAO,CAAC,KAAK,CAAC,YAAY,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;QAC3C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,eAAe,CAAC,OAAe,EAAE,UAAkB,EAAE,SAAiB;IACnF,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IAEhD,gCAAgC;IAChC,IAAI,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAC1B,OAAO,CAAC,KAAK,CAAC,cAAc,OAAO,kBAAkB,CAAC,CAAC;QACvD,OAAO,CAAC,KAAK,CAAC,0CAA0C,OAAO,EAAE,CAAC,CAAC;QACnE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,MAAM,GAAG;qCACoB,UAAU;EAC7C,SAAS,QAAQ,UAAU;CAC5B,CAAC;IAEA,MAAM,EAAE,CAAC,SAAS,CAAC,SAAS,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;AACzD,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,kBAAkB,CAAC,OAAe,EAAE,UAAkB,EAAE,SAAiB;IACtF,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,OAAO,MAAM,CAAC,CAAC;IAEzD,gCAAgC;IAChC,IAAI,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAC1B,OAAO,CAAC,KAAK,CAAC,cAAc,OAAO,kBAAkB,CAAC,CAAC;QACvD,OAAO,CAAC,KAAK,CAAC,0CAA0C,OAAO,EAAE,CAAC,CAAC;QACnE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,MAAM,GAAG;uCACsB,UAAU;EAC/C,SAAS,QAAQ,UAAU;CAC5B,CAAC;IAEA,MAAM,EAAE,CAAC,SAAS,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;AACxC,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,oBAAoB;IACjC,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC;IACvC,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;IAE5C,IAAI,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;QAC9B,kBAAkB;QAClB,OAAO;IACT,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,SAAS,SAAS,sBAAsB,CAAC,CAAC;IAEtD,IAAI,UAAU,EAAE,CAAC;QACf,OAAO,CAAC,GAAG,CAAC,qEAAqE,CAAC,CAAC;QACnF,OAAO,CAAC,GAAG,CAAC,mEAAmE,SAAS,YAAY,CAAC,CAAC;QACtG,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC;QACrC,OAAO,CAAC,GAAG,CAAC,yDAAyD,CAAC,CAAC;QACvE,OAAO,CAAC,GAAG,CAAC,+CAA+C,CAAC,CAAC;QAC7D,OAAO,CAAC,GAAG,CAAC,eAAe,SAAS,EAAE,CAAC,CAAC;QACxC,OAAO,CAAC,GAAG,CAAC,8BAA8B,CAAC,CAAC;IAC9C,CAAC;SAAM,CAAC;QACN,eAAe;QACf,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC;QACtC,IAAI,UAAU,GAAG,WAAW,CAAC;QAE7B,IAAI,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;YAC1B,UAAU,GAAG,UAAU,CAAC;QAC1B,CAAC;aAAM,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;YAClC,UAAU,GAAG,4BAA4B,CAAC;QAC5C,CAAC;QAED,OAAO,CAAC,GAAG,CAAC,sBAAsB,UAAU,GAAG,CAAC,CAAC;QACjD,OAAO,CAAC,GAAG,CAAC,0BAA0B,SAAS,GAAG,CAAC,CAAC;QACpD,OAAO,CAAC,GAAG,CAAC,2BAA2B,CAAC,CAAC;QACzC,OAAO,CAAC,GAAG,CAAC,cAAc,UAAU,EAAE,CAAC,CAAC;IAC1C,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,SAAiB;IACjD,IAAI,CAAC;QACH,oCAAoC;QACpC,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;QACjD,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,SAAS,MAAM,CAAC,CAAC;QAE7D,IAAI,SAAS,GAAkB,IAAI,CAAC;QAEpC,IAAI,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YACzB,SAAS,GAAG,QAAQ,CAAC;QACvB,CAAC;aAAM,IAAI,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;YACnC,SAAS,GAAG,WAAW,CAAC;QAC1B,CAAC;QAED,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,YAAY,SAAS,aAAa,CAAC,CAAC;YAClD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,MAAM,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QAC3B,OAAO,CAAC,GAAG,CAAC,oBAAoB,SAAS,EAAE,CAAC,CAAC;IAC/C,CAAC;IAAC,OAAO,KAAU,EAAE,CAAC;QACpB,OAAO,CAAC,KAAK,CAAC,YAAY,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;QAC3C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW;IAC/B,IAAI,CAAC;QACH,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YAC3B,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC;YACvC,OAAO,CAAC,GAAG,CAAC,+CAA+C,CAAC,CAAC;YAC7D,OAAO;QACT,CAAC;QAED,MAAM,KAAK,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QAE1C,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACvB,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC;YACvC,OAAO,CAAC,GAAG,CAAC,+CAA+C,CAAC,CAAC;YAC7D,OAAO;QACT,CAAC;QAED,OAAO,CAAC,GAAG,CAAC,kBAAkB,SAAS,MAAM,CAAC,CAAC;QAE/C,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;YAC7C,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YAEtC,IAAI,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;gBAClB,oDAAoD;gBACpD,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;gBACtD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC;gBAChD,MAAM,UAAU,GAAG,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;gBAEhD,iDAAiD;gBACjD,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;gBAC/C,OAAO,CAAC,GAAG,CAAC,OAAO,WAAW,iBAAiB,UAAU,EAAE,CAAC,CAAC;YAC/D,CAAC;QACH,CAAC;QAED,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAEhB,oCAAoC;QACpC,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC;QACvC,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;QAE5C,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;YAC/B,MAAM,oBAAoB,EAAE,CAAC;QAC/B,CAAC;IACH,CAAC;IAAC,OAAO,KAAU,EAAE,CAAC;QACpB,OAAO,CAAC,KAAK,CAAC,YAAY,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;QAC3C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,oBAAoB;IACjC,4CAA4C;IAC5C,MAAM,YAAY,GAAG,MAAM,UAAU,CAAC,QAAQ,CAAC,CAAC;IAChD,IAAI,YAAY,EAAE,CAAC;QACjB,OAAO,YAAY,CAAC;IACtB,CAAC;IAED,kBAAkB;IAClB,OAAO,oBAAoB,CAAC;AAC9B,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,UAAU,CAAC,GAAW;IACnC,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC;IACvC,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAEjC,KAAK,MAAM,GAAG,IAAI,KAAK,EAAE,CAAC;QACxB,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;QACrC,IAAI,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YACzB,IAAI,CAAC;gBACH,MAAM,EAAE,CAAC,MAAM,CAAC,QAAQ,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;gBAC7C,OAAO,QAAQ,CAAC;YAClB,CAAC;YAAC,MAAM,CAAC;gBACP,SAAS;YACX,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC"}
|