@padua/cli 2.0.24 → 2.0.25

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 CHANGED
@@ -54,6 +54,7 @@ The `init` command will:
54
54
  | | Status | Health check for all authentication services |
55
55
  | | Doctor | Configuration validation and diagnostics with fuzzy profile matching |
56
56
  | **Tunnel** | RDS | Secure tunnels to RDS/Aurora databases via SSM |
57
+ | | LB | Port forwarding to internal ALB via SSM |
57
58
  | **Exec** | ECS | Interactive shell in running ECS containers via SSM |
58
59
  | **MCP** | Server | Built-in MCP server with 49 GitLab and Atlassian tools |
59
60
  | | Daemon | Background process management via `padua login` |
@@ -302,7 +303,7 @@ Returns:
302
303
  "atlassian": "ready"
303
304
  },
304
305
  "uptime": 3600,
305
- "version": "2.0.23"
306
+ "version": "2.0.25"
306
307
  }
307
308
  ```
308
309
 
@@ -789,15 +790,27 @@ paws clear
789
790
 
790
791
  ## Tunnel Command
791
792
 
792
- Create secure tunnels to RDS databases via SSM Session Manager.
793
+ Create secure tunnels to AWS resources via SSM Session Manager.
793
794
 
794
795
  Automatically reads `AWS_PROFILE` environment variable when no `--profile` flag is provided (works with `paws`).
795
796
 
797
+ ### Targets
798
+
799
+ | Target | Description | System Required |
800
+ |--------|-------------|-----------------|
801
+ | `rds` | Tunnel to RDS/Aurora databases | Yes (e.g., `roma`, `padua-iam`) |
802
+ | `lb` | Tunnel to internal ALB (`dev.int.paduasolutions.net:443`) | No |
803
+
796
804
  ### Basic Usage
797
805
 
798
806
  ```bash
807
+ # RDS tunnel (requires system argument)
799
808
  padua tunnel roma rds # Interactive (prompts for port/cluster)
800
809
  padua tunnel roma rds -p paduafg-development # Use specific profile
810
+
811
+ # Load balancer tunnel (no system needed)
812
+ padua tunnel lb # Interactive (prompts for port, default 8443)
813
+ padua tunnel lb --local-port 9443 # Use specific local port
801
814
  ```
802
815
 
803
816
  ### Options
@@ -806,11 +819,11 @@ padua tunnel roma rds -p paduafg-development # Use specific profile
806
819
  |------|-------------|
807
820
  | `-p, --profile <name>` | AWS profile to use |
808
821
  | `--local-port <port>` | Local port for the tunnel |
809
- | `--cluster <name>` | RDS cluster or instance name |
822
+ | `--cluster <name>` | RDS cluster or instance name (RDS only) |
810
823
  | `-v, --verbose` | Show detailed output |
811
824
  | `--no-color` | Disable colored output |
812
825
 
813
- ### System Configuration
826
+ ### RDS System Configuration
814
827
 
815
828
  Different systems use different EC2 instances as tunnel endpoints:
816
829
 
@@ -819,7 +832,22 @@ Different systems use different EC2 instances as tunnel endpoints:
819
832
  | roma | bastion-host | 3306 (MySQL) | roma-backend |
820
833
  | (others) | jumpbox | 5432 (PostgreSQL) | (none) |
821
834
 
822
- ### Example Output
835
+ ### LB Tunnel Usage
836
+
837
+ The internal ALB uses path-based routing for most services. Once the tunnel is running:
838
+
839
+ ```bash
840
+ # Path-based services (most services)
841
+ curl -k https://localhost:8443/echo/test
842
+ curl -k https://localhost:8443/wealth-summaries/healthz
843
+ curl -k https://localhost:8443/entity-management/api/v1/status
844
+
845
+ # Host-based services (permify)
846
+ curl -k https://localhost:8443/v1/permissions/check \
847
+ -H "Host: permify.dev.int.paduasolutions.net"
848
+ ```
849
+
850
+ ### Example Output (RDS)
823
851
 
824
852
  ```
825
853
  Checking port 3306 availability...
@@ -839,6 +867,30 @@ Starting tunnel...
839
867
  Press Ctrl+C to close the tunnel
840
868
  ```
841
869
 
870
+ ### Example Output (LB)
871
+
872
+ ```
873
+ Checking port 8443 availability...
874
+ ✓ Port 8443 is available
875
+ Looking up jumpbox instance...
876
+ ✓ Found instance: i-0abc123def456
877
+
878
+ Starting tunnel...
879
+ Profile: paduafg-development
880
+ Local port: 8443
881
+ Remote: dev.int.paduasolutions.net:443
882
+ Via: i-0abc123def456 (jumpbox)
883
+
884
+ Usage (path-based services):
885
+ curl -k https://localhost:8443/<service>/path
886
+ e.g. curl -k https://localhost:8443/echo/test
887
+
888
+ Usage (host-based services like permify):
889
+ curl -k https://localhost:8443/path -H "Host: <service>.dev.int.paduasolutions.net"
890
+
891
+ Press Ctrl+C to close the tunnel
892
+ ```
893
+
842
894
  ## Exec Command
843
895
 
844
896
  Open an interactive shell in a running ECS container via SSM Execute Command.
@@ -7,6 +7,6 @@ export declare const tunnelCommand: Command;
7
7
  /**
8
8
  * Handle the tunnel command
9
9
  */
10
- declare function handleTunnel(system: string, target: string, options: TunnelOptions): Promise<void>;
10
+ declare function handleTunnel(system: string, target: string | undefined, options: TunnelOptions): Promise<void>;
11
11
  export { handleTunnel };
12
12
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/tunnel/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAI3C;;GAEG;AACH,eAAO,MAAM,aAAa,SASH,CAAC;AAExB;;GAEG;AACH,iBAAe,YAAY,CACzB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,aAAa,GACrB,OAAO,CAAC,IAAI,CAAC,CA8Cf;AAGD,OAAO,EAAE,YAAY,EAAE,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/tunnel/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAK3C;;GAEG;AACH,eAAO,MAAM,aAAa,SASH,CAAC;AAExB;;GAEG;AACH,iBAAe,YAAY,CACzB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,OAAO,EAAE,aAAa,GACrB,OAAO,CAAC,IAAI,CAAC,CAqEf;AAGD,OAAO,EAAE,YAAY,EAAE,CAAC"}
@@ -1,14 +1,15 @@
1
1
  import { Command } from 'commander';
2
2
  import chalk from 'chalk';
3
3
  import { startRdsTunnel } from './rds.js';
4
+ import { startLbTunnel } from './lb.js';
4
5
  import { checkSessionManagerPlugin } from '../init/prerequisites.js';
5
6
  /**
6
7
  * Tunnel command - create secure tunnels to AWS resources via SSM
7
8
  */
8
9
  export const tunnelCommand = new Command('tunnel')
9
10
  .description('Create secure tunnels to AWS resources via SSM Session Manager')
10
- .argument('<system>', 'Target system (e.g., roma, padua-iam)')
11
- .argument('<target>', 'Target service type (rds)')
11
+ .argument('<system>', 'Target system (e.g., roma, padua-iam) or target type (lb)')
12
+ .argument('[target]', 'Target service type (rds, lb)')
12
13
  .option('-p, --profile <name>', 'AWS profile to use')
13
14
  .option('--local-port <port>', 'Local port for the tunnel')
14
15
  .option('--cluster <name>', 'RDS cluster or instance name')
@@ -33,8 +34,24 @@ async function handleTunnel(system, target, options) {
33
34
  }
34
35
  process.exit(1);
35
36
  }
37
+ // Smart target detection: if system is a valid target and no target provided
38
+ const validTargets = ['rds', 'lb'];
39
+ if (target === undefined && validTargets.includes(system.toLowerCase())) {
40
+ target = system;
41
+ system = '';
42
+ }
43
+ if (target === undefined) {
44
+ if (!noColor) {
45
+ console.error(chalk.red('Target is required.'));
46
+ console.error(chalk.gray(`Valid targets: ${validTargets.join(', ')}`));
47
+ }
48
+ else {
49
+ console.error('Target is required.');
50
+ console.error(`Valid targets: ${validTargets.join(', ')}`);
51
+ }
52
+ process.exit(1);
53
+ }
36
54
  // Validate target type
37
- const validTargets = ['rds'];
38
55
  if (!validTargets.includes(target.toLowerCase())) {
39
56
  if (!noColor) {
40
57
  console.error(chalk.red(`Invalid target: ${target}`));
@@ -49,8 +66,14 @@ async function handleTunnel(system, target, options) {
49
66
  try {
50
67
  switch (target.toLowerCase()) {
51
68
  case 'rds':
69
+ if (!system) {
70
+ throw new Error('System argument is required for RDS tunnels (e.g., padua tunnel roma rds)');
71
+ }
52
72
  await startRdsTunnel(system, options);
53
73
  break;
74
+ case 'lb':
75
+ await startLbTunnel(options);
76
+ break;
54
77
  default:
55
78
  throw new Error(`Unsupported target: ${target}`);
56
79
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/commands/tunnel/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAC1C,OAAO,EAAE,yBAAyB,EAAE,MAAM,0BAA0B,CAAC;AAErE;;GAEG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,IAAI,OAAO,CAAC,QAAQ,CAAC;KAC/C,WAAW,CAAC,gEAAgE,CAAC;KAC7E,QAAQ,CAAC,UAAU,EAAE,uCAAuC,CAAC;KAC7D,QAAQ,CAAC,UAAU,EAAE,2BAA2B,CAAC;KACjD,MAAM,CAAC,sBAAsB,EAAE,oBAAoB,CAAC;KACpD,MAAM,CAAC,qBAAqB,EAAE,2BAA2B,CAAC;KAC1D,MAAM,CAAC,kBAAkB,EAAE,8BAA8B,CAAC;KAC1D,MAAM,CAAC,eAAe,EAAE,sBAAsB,CAAC;KAC/C,MAAM,CAAC,YAAY,EAAE,wBAAwB,CAAC;KAC9C,MAAM,CAAC,YAAY,CAAC,CAAC;AAExB;;GAEG;AACH,KAAK,UAAU,YAAY,CACzB,MAAc,EACd,MAAc,EACd,OAAsB;IAEtB,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,KAAK,CAAC;IAEzC,sBAAsB;IACtB,MAAM,QAAQ,GAAG,yBAAyB,EAAE,CAAC;IAC7C,IAAI,CAAC,QAAQ,CAAC,SAAS,EAAE,CAAC;QACxB,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,mDAAmD,CAAC,CAAC,CAAC;YAC9E,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,YAAY,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC;QAC/D,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,KAAK,CAAC,mDAAmD,CAAC,CAAC;YACnE,OAAO,CAAC,KAAK,CAAC,YAAY,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC;QACnD,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,uBAAuB;IACvB,MAAM,YAAY,GAAG,CAAC,KAAK,CAAC,CAAC;IAC7B,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC,EAAE,CAAC;QACjD,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,mBAAmB,MAAM,EAAE,CAAC,CAAC,CAAC;YACtD,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,kBAAkB,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;QACzE,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,KAAK,CAAC,mBAAmB,MAAM,EAAE,CAAC,CAAC;YAC3C,OAAO,CAAC,KAAK,CAAC,kBAAkB,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC7D,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,IAAI,CAAC;QACH,QAAQ,MAAM,CAAC,WAAW,EAAE,EAAE,CAAC;YAC7B,KAAK,KAAK;gBACR,MAAM,cAAc,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;gBACtC,MAAM;YACR;gBACE,MAAM,IAAI,KAAK,CAAC,uBAAuB,MAAM,EAAE,CAAC,CAAC;QACrD,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,OAAO,GAAI,KAAe,CAAC,OAAO,CAAC;QACzC,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,OAAO,EAAE,CAAC,CAAC,CAAC;QAChD,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,KAAK,CAAC,UAAU,OAAO,EAAE,CAAC,CAAC;QACrC,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC;AAED,sBAAsB;AACtB,OAAO,EAAE,YAAY,EAAE,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/commands/tunnel/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import { TunnelOptions } from './types.js';
2
+ /**
3
+ * Start an LB tunnel via SSM Session Manager to the internal ALB
4
+ */
5
+ export declare function startLbTunnel(options: TunnelOptions): Promise<void>;
6
+ //# sourceMappingURL=lb.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lb.d.ts","sourceRoot":"","sources":["../../../src/commands/tunnel/lb.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAW3C;;GAEG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CA+IzE"}
@@ -0,0 +1,148 @@
1
+ import { spawn } from 'child_process';
2
+ import chalk from 'chalk';
3
+ import inquirer from 'inquirer';
4
+ import { getInstanceIdByTag } from './aws.js';
5
+ import { isPortAvailable, parsePort } from './port.js';
6
+ import { getSubprocessEnv, sanitizeOutput } from '../login/utils.js';
7
+ import { loadConfig } from '../login/config.js';
8
+ import { getEffectiveProfile } from '../login/types.js';
9
+ const ALB_REMOTE_HOST = 'dev.int.paduasolutions.net';
10
+ const ALB_REMOTE_PORT = 443;
11
+ const LB_DEFAULT_LOCAL_PORT = 8443;
12
+ /**
13
+ * Start an LB tunnel via SSM Session Manager to the internal ALB
14
+ */
15
+ export async function startLbTunnel(options) {
16
+ const noColor = options.noColor ?? false;
17
+ // Load config and get profile
18
+ const config = await loadConfig();
19
+ const profile = getEffectiveProfile({ profile: options.profile }, config ?? undefined);
20
+ // Step 1: Resolve local port
21
+ let localPort;
22
+ if (options.localPort) {
23
+ const parsed = parsePort(options.localPort);
24
+ if (!parsed) {
25
+ throw new Error(`Invalid port: ${options.localPort}`);
26
+ }
27
+ localPort = parsed;
28
+ }
29
+ else {
30
+ const portAnswer = await inquirer.prompt([
31
+ {
32
+ type: 'input',
33
+ name: 'port',
34
+ message: 'Local port for ALB tunnel:',
35
+ default: LB_DEFAULT_LOCAL_PORT.toString(),
36
+ validate: (input) => {
37
+ const p = parsePort(input);
38
+ if (!p)
39
+ return 'Please enter a valid port number (1-65535)';
40
+ return true;
41
+ },
42
+ },
43
+ ]);
44
+ localPort = parsePort(portAnswer.port);
45
+ }
46
+ // Step 2: Verify port availability
47
+ if (!noColor) {
48
+ console.log(chalk.gray(`Checking port ${localPort} availability...`));
49
+ }
50
+ const portAvailable = await isPortAvailable(localPort);
51
+ if (!portAvailable) {
52
+ throw new Error(`Port ${localPort} is already in use. Please choose a different port.`);
53
+ }
54
+ if (!noColor) {
55
+ console.log(chalk.green(`✓ Port ${localPort} is available`));
56
+ }
57
+ else {
58
+ console.log(`Port ${localPort} is available`);
59
+ }
60
+ // Step 3: Get jumpbox instance ID
61
+ if (!noColor) {
62
+ console.log(chalk.gray('Looking up jumpbox instance...'));
63
+ }
64
+ else {
65
+ console.log('Looking up jumpbox instance...');
66
+ }
67
+ const instanceId = getInstanceIdByTag('jumpbox', profile, options.verbose);
68
+ if (!noColor) {
69
+ console.log(chalk.green(`✓ Found instance: ${instanceId}`));
70
+ }
71
+ else {
72
+ console.log(`Found instance: ${instanceId}`);
73
+ }
74
+ // Step 4: Print tunnel summary
75
+ console.log('');
76
+ if (!noColor) {
77
+ console.log(chalk.cyan.bold('Starting tunnel...'));
78
+ console.log(chalk.gray(` Profile: ${profile}`));
79
+ console.log(chalk.gray(` Local port: ${localPort}`));
80
+ console.log(chalk.gray(` Remote: ${ALB_REMOTE_HOST}:${ALB_REMOTE_PORT}`));
81
+ console.log(chalk.gray(` Via: ${instanceId} (jumpbox)`));
82
+ }
83
+ else {
84
+ console.log('Starting tunnel...');
85
+ console.log(` Profile: ${profile}`);
86
+ console.log(` Local port: ${localPort}`);
87
+ console.log(` Remote: ${ALB_REMOTE_HOST}:${ALB_REMOTE_PORT}`);
88
+ console.log(` Via: ${instanceId} (jumpbox)`);
89
+ }
90
+ console.log('');
91
+ if (!noColor) {
92
+ console.log(chalk.cyan('Usage (path-based services):'));
93
+ console.log(chalk.gray(` curl -k https://localhost:${localPort}/<service>/path`));
94
+ console.log(chalk.gray(` e.g. curl -k https://localhost:${localPort}/echo/test`));
95
+ console.log('');
96
+ console.log(chalk.cyan('Usage (host-based services like permify):'));
97
+ console.log(chalk.gray(` curl -k https://localhost:${localPort}/path -H "Host: <service>.${ALB_REMOTE_HOST}"`));
98
+ }
99
+ else {
100
+ console.log('Usage (path-based services):');
101
+ console.log(` curl -k https://localhost:${localPort}/<service>/path`);
102
+ console.log(` e.g. curl -k https://localhost:${localPort}/echo/test`);
103
+ console.log('');
104
+ console.log('Usage (host-based services like permify):');
105
+ console.log(` curl -k https://localhost:${localPort}/path -H "Host: <service>.${ALB_REMOTE_HOST}"`);
106
+ }
107
+ console.log('');
108
+ if (!noColor) {
109
+ console.log(chalk.yellow('Press Ctrl+C to close the tunnel'));
110
+ }
111
+ else {
112
+ console.log('Press Ctrl+C to close the tunnel');
113
+ }
114
+ console.log('');
115
+ // Step 5: Start SSM session
116
+ const child = spawn('aws', [
117
+ 'ssm',
118
+ 'start-session',
119
+ '--target', instanceId,
120
+ '--document-name', 'AWS-StartPortForwardingSessionToRemoteHost',
121
+ '--parameters', `host="${ALB_REMOTE_HOST}",portNumber="${ALB_REMOTE_PORT}",localPortNumber="${localPort}"`,
122
+ '--profile', profile,
123
+ ], {
124
+ stdio: 'inherit',
125
+ env: { ...getSubprocessEnv(), AWS_PROFILE: profile },
126
+ });
127
+ // Handle process lifecycle
128
+ await new Promise((resolve, reject) => {
129
+ child.on('error', (error) => {
130
+ reject(new Error(`Failed to start SSM session: ${sanitizeOutput(error.message)}`));
131
+ });
132
+ child.on('exit', (code) => {
133
+ if (code !== 0 && code !== null) {
134
+ console.log('');
135
+ if (!noColor) {
136
+ console.log(chalk.red(`Tunnel closed with exit code: ${code}`));
137
+ }
138
+ else {
139
+ console.log(`Tunnel closed with exit code: ${code}`);
140
+ }
141
+ }
142
+ });
143
+ child.on('close', () => {
144
+ resolve();
145
+ });
146
+ });
147
+ }
148
+ //# sourceMappingURL=lb.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lb.js","sourceRoot":"","sources":["../../../src/commands/tunnel/lb.ts"],"names":[],"mappings":"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"}
@@ -4,7 +4,7 @@
4
4
  /**
5
5
  * Tunnel target types
6
6
  */
7
- export type TunnelTarget = 'rds' | 'opensearch' | 'ec2';
7
+ export type TunnelTarget = 'rds' | 'opensearch' | 'ec2' | 'lb';
8
8
  /**
9
9
  * Options for the tunnel command
10
10
  */
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/commands/tunnel/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG,KAAK,GAAG,YAAY,GAAG,KAAK,CAAC;AAExD;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,2CAA2C;IAC3C,MAAM,EAAE,MAAM,CAAC;IACf,+BAA+B;IAC/B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,4BAA4B;IAC5B,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;;;GAIG;AACH,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAMvD,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,qBAAqB,EAAE,YAGnC,CAAC;AAEF;;GAEG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,YAAY,CAE5D;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CA2B/E"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/commands/tunnel/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG,KAAK,GAAG,YAAY,GAAG,KAAK,GAAG,IAAI,CAAC;AAE/D;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,2CAA2C;IAC3C,MAAM,EAAE,MAAM,CAAC;IACf,+BAA+B;IAC/B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,4BAA4B;IAC5B,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;;;GAIG;AACH,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAMvD,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,qBAAqB,EAAE,YAGnC,CAAC;AAEF;;GAEG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,YAAY,CAE5D;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CA2B/E"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@padua/cli",
3
- "version": "2.0.24",
3
+ "version": "2.0.25",
4
4
  "description": "Unified AWS infrastructure management CLI",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",