pipenet 1.0.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/.github/workflows/feature.yaml +39 -0
- package/.github/workflows/main.yaml +41 -0
- package/LICENSE +49 -0
- package/README.md +114 -0
- package/dist/HeaderHostTransformer.d.ts +11 -0
- package/dist/HeaderHostTransformer.d.ts.map +1 -0
- package/dist/HeaderHostTransformer.js +19 -0
- package/dist/HeaderHostTransformer.js.map +1 -0
- package/dist/Tunnel.d.ts +29 -0
- package/dist/Tunnel.d.ts.map +1 -0
- package/dist/Tunnel.js +132 -0
- package/dist/Tunnel.js.map +1 -0
- package/dist/TunnelCluster.d.ts +27 -0
- package/dist/TunnelCluster.d.ts.map +1 -0
- package/dist/TunnelCluster.js +101 -0
- package/dist/TunnelCluster.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +161 -0
- package/dist/cli.js.map +1 -0
- package/dist/pipenet.d.ts +17 -0
- package/dist/pipenet.d.ts.map +1 -0
- package/dist/pipenet.js +16 -0
- package/dist/pipenet.js.map +1 -0
- package/dist/pipenet.spec.d.ts +2 -0
- package/dist/pipenet.spec.d.ts.map +1 -0
- package/dist/pipenet.spec.js +67 -0
- package/dist/pipenet.spec.js.map +1 -0
- package/dist/server/Client.d.ts +20 -0
- package/dist/server/Client.d.ts.map +1 -0
- package/dist/server/Client.js +91 -0
- package/dist/server/Client.js.map +1 -0
- package/dist/server/Client.spec.d.ts +2 -0
- package/dist/server/Client.spec.d.ts.map +1 -0
- package/dist/server/Client.spec.js +117 -0
- package/dist/server/Client.spec.js.map +1 -0
- package/dist/server/ClientManager.d.ts +23 -0
- package/dist/server/ClientManager.d.ts.map +1 -0
- package/dist/server/ClientManager.js +64 -0
- package/dist/server/ClientManager.js.map +1 -0
- package/dist/server/ClientManager.spec.d.ts +2 -0
- package/dist/server/ClientManager.spec.d.ts.map +1 -0
- package/dist/server/ClientManager.spec.js +74 -0
- package/dist/server/ClientManager.spec.js.map +1 -0
- package/dist/server/TunnelAgent.d.ts +32 -0
- package/dist/server/TunnelAgent.d.ts.map +1 -0
- package/dist/server/TunnelAgent.js +110 -0
- package/dist/server/TunnelAgent.js.map +1 -0
- package/dist/server/TunnelAgent.spec.d.ts +2 -0
- package/dist/server/TunnelAgent.spec.d.ts.map +1 -0
- package/dist/server/TunnelAgent.spec.js +109 -0
- package/dist/server/TunnelAgent.spec.js.map +1 -0
- package/dist/server/index.d.ts +5 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +5 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/server.d.ts +9 -0
- package/dist/server/server.d.ts.map +1 -0
- package/dist/server/server.js +129 -0
- package/dist/server/server.js.map +1 -0
- package/dist/server/server.spec.d.ts +2 -0
- package/dist/server/server.spec.d.ts.map +1 -0
- package/dist/server/server.spec.js +113 -0
- package/dist/server/server.spec.js.map +1 -0
- package/eslint.config.ts +28 -0
- package/package.json +73 -0
- package/src/HeaderHostTransformer.ts +29 -0
- package/src/Tunnel.ts +202 -0
- package/src/TunnelCluster.ts +166 -0
- package/src/cli.ts +204 -0
- package/src/pipenet.spec.ts +82 -0
- package/src/pipenet.ts +39 -0
- package/src/server/Client.spec.ts +139 -0
- package/src/server/Client.ts +114 -0
- package/src/server/ClientManager.spec.ts +90 -0
- package/src/server/ClientManager.ts +82 -0
- package/src/server/TunnelAgent.spec.ts +142 -0
- package/src/server/TunnelAgent.ts +135 -0
- package/src/server/index.ts +4 -0
- package/src/server/server.spec.ts +139 -0
- package/src/server/server.ts +171 -0
- package/src/types/human-readable-ids.d.ts +5 -0
- package/tsconfig.json +20 -0
- package/vitest.config.ts +10 -0
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
name: Run Tests
|
|
2
|
+
on:
|
|
3
|
+
pull_request:
|
|
4
|
+
branches:
|
|
5
|
+
- main
|
|
6
|
+
types:
|
|
7
|
+
- opened
|
|
8
|
+
- synchronize
|
|
9
|
+
- reopened
|
|
10
|
+
- ready_for_review
|
|
11
|
+
jobs:
|
|
12
|
+
test:
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
name: Test
|
|
15
|
+
strategy:
|
|
16
|
+
fail-fast: true
|
|
17
|
+
matrix:
|
|
18
|
+
node:
|
|
19
|
+
- 24
|
|
20
|
+
steps:
|
|
21
|
+
- name: Checkout repository
|
|
22
|
+
uses: actions/checkout@v4
|
|
23
|
+
with:
|
|
24
|
+
fetch-depth: 0
|
|
25
|
+
- uses: pnpm/action-setup@v4
|
|
26
|
+
with:
|
|
27
|
+
version: 9
|
|
28
|
+
- name: Setup NodeJS ${{ matrix.node }}
|
|
29
|
+
uses: actions/setup-node@v4
|
|
30
|
+
with:
|
|
31
|
+
node-version: ${{ matrix.node }}
|
|
32
|
+
cache: "pnpm"
|
|
33
|
+
cache-dependency-path: "**/pnpm-lock.yaml"
|
|
34
|
+
- name: Install dependencies
|
|
35
|
+
run: pnpm install
|
|
36
|
+
- name: Run lint
|
|
37
|
+
run: pnpm lint
|
|
38
|
+
- name: Run tests
|
|
39
|
+
run: pnpm test
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
on:
|
|
3
|
+
push:
|
|
4
|
+
branches:
|
|
5
|
+
- main
|
|
6
|
+
jobs:
|
|
7
|
+
test:
|
|
8
|
+
environment: release
|
|
9
|
+
name: Test
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
permissions:
|
|
12
|
+
contents: write
|
|
13
|
+
issues: write
|
|
14
|
+
pull-requests: write
|
|
15
|
+
id-token: write
|
|
16
|
+
steps:
|
|
17
|
+
- name: setup repository
|
|
18
|
+
uses: actions/checkout@v4
|
|
19
|
+
with:
|
|
20
|
+
fetch-depth: 0
|
|
21
|
+
- uses: pnpm/action-setup@v4
|
|
22
|
+
with:
|
|
23
|
+
version: 9
|
|
24
|
+
- name: Setup NodeJS
|
|
25
|
+
uses: actions/setup-node@v4
|
|
26
|
+
with:
|
|
27
|
+
node-version: 24
|
|
28
|
+
cache: "pnpm"
|
|
29
|
+
cache-dependency-path: "**/pnpm-lock.yaml"
|
|
30
|
+
- name: Install dependencies
|
|
31
|
+
run: pnpm install
|
|
32
|
+
- name: Run lint
|
|
33
|
+
run: pnpm lint
|
|
34
|
+
- name: Run tests
|
|
35
|
+
run: pnpm test
|
|
36
|
+
- name: Build
|
|
37
|
+
run: pnpm build
|
|
38
|
+
- name: Release
|
|
39
|
+
run: pnpm semantic-release
|
|
40
|
+
env:
|
|
41
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
package/LICENSE
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
=====================
|
|
3
|
+
|
|
4
|
+
Copyright © 2026 Frank Fiegel (frank@glama.ai)
|
|
5
|
+
|
|
6
|
+
Permission is hereby granted, free of charge, to any person
|
|
7
|
+
obtaining a copy of this software and associated documentation
|
|
8
|
+
files (the “Software”), to deal in the Software without
|
|
9
|
+
restriction, including without limitation the rights to use,
|
|
10
|
+
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
11
|
+
copies of the Software, and to permit persons to whom the
|
|
12
|
+
Software is furnished to do so, subject to the following
|
|
13
|
+
conditions:
|
|
14
|
+
|
|
15
|
+
The above copyright notice and this permission notice shall be
|
|
16
|
+
included in all copies or substantial portions of the Software.
|
|
17
|
+
|
|
18
|
+
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND,
|
|
19
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
|
20
|
+
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
21
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
22
|
+
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
23
|
+
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
24
|
+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
25
|
+
OTHER DEALINGS IN THE SOFTWARE.
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
MIT License
|
|
30
|
+
|
|
31
|
+
Copyright (c) 2018 Roman Shtylman
|
|
32
|
+
|
|
33
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
34
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
35
|
+
in the Software without restriction, including without limitation the rights
|
|
36
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
37
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
38
|
+
furnished to do so, subject to the following conditions:
|
|
39
|
+
|
|
40
|
+
The above copyright notice and this permission notice shall be included in all
|
|
41
|
+
copies or substantial portions of the Software.
|
|
42
|
+
|
|
43
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
44
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
45
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
46
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
47
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
48
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
49
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# pipenet
|
|
2
|
+
|
|
3
|
+
pipenet exposes your localhost to the world for easy testing and sharing! No need to mess with DNS or deploy just to have others test out your changes.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install pipenet
|
|
9
|
+
# or
|
|
10
|
+
pnpm add pipenet
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## API
|
|
14
|
+
|
|
15
|
+
The pipenet client is also usable through an API (for test integration, automation, etc)
|
|
16
|
+
|
|
17
|
+
### pipenet(port [,options][,callback])
|
|
18
|
+
|
|
19
|
+
Creates a new pipenet tunnel to the specified local `port`. Will return a Promise that resolves once you have been assigned a public tunnel url. `options` can be used to request a specific `subdomain`. A `callback` function can be passed, in which case it won't return a Promise. This exists for backwards compatibility with the old Node-style callback API. You may also pass a single options object with `port` as a property.
|
|
20
|
+
|
|
21
|
+
```js
|
|
22
|
+
import pipenet from 'pipenet';
|
|
23
|
+
|
|
24
|
+
const tunnel = await pipenet({ port: 3000 });
|
|
25
|
+
|
|
26
|
+
// the assigned public url for your tunnel
|
|
27
|
+
// i.e. https://abcdefgjhij.pipenet.me
|
|
28
|
+
tunnel.url;
|
|
29
|
+
|
|
30
|
+
tunnel.on('close', () => {
|
|
31
|
+
// tunnels are closed
|
|
32
|
+
});
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
#### options
|
|
36
|
+
|
|
37
|
+
- `port` (number) [required] The local port number to expose through pipenet.
|
|
38
|
+
- `subdomain` (string) Request a specific subdomain on the proxy server. **Note** You may not actually receive this name depending on availability.
|
|
39
|
+
- `host` (string) URL for the upstream proxy server. Defaults to `https://pipenet.me`.
|
|
40
|
+
- `local_host` (string) Proxy to this hostname instead of `localhost`. This will also cause the `Host` header to be re-written to this value in proxied requests.
|
|
41
|
+
- `local_https` (boolean) Enable tunneling to local HTTPS server.
|
|
42
|
+
- `local_cert` (string) Path to certificate PEM file for local HTTPS server.
|
|
43
|
+
- `local_key` (string) Path to certificate key file for local HTTPS server.
|
|
44
|
+
- `local_ca` (string) Path to certificate authority file for self-signed certificates.
|
|
45
|
+
- `allow_invalid_cert` (boolean) Disable certificate checks for your local HTTPS server (ignore cert/key/ca options).
|
|
46
|
+
|
|
47
|
+
Refer to [tls.createSecureContext](https://nodejs.org/api/tls.html#tls_tls_createsecurecontext_options) for details on the certificate options.
|
|
48
|
+
|
|
49
|
+
### Tunnel
|
|
50
|
+
|
|
51
|
+
The `tunnel` instance returned to your callback emits the following events
|
|
52
|
+
|
|
53
|
+
| event | args | description |
|
|
54
|
+
| ------- | ---- | ------------------------------------------------------------------------------------ |
|
|
55
|
+
| request | info | fires when a request is processed by the tunnel, contains _method_ and _path_ fields |
|
|
56
|
+
| error | err | fires when an error happens on the tunnel |
|
|
57
|
+
| close | | fires when the tunnel has closed |
|
|
58
|
+
|
|
59
|
+
The `tunnel` instance has the following methods
|
|
60
|
+
|
|
61
|
+
| method | args | description |
|
|
62
|
+
| ------ | ---- | ---------------- |
|
|
63
|
+
| close | | close the tunnel |
|
|
64
|
+
|
|
65
|
+
## Server
|
|
66
|
+
|
|
67
|
+
This package includes both the client and server components. You can run your own pipenet server.
|
|
68
|
+
|
|
69
|
+
### Running the Server
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
# Using the CLI
|
|
73
|
+
npx pipenet-server --port 3000
|
|
74
|
+
|
|
75
|
+
# Or programmatically
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
```js
|
|
79
|
+
import { createServer } from 'pipenet/server';
|
|
80
|
+
|
|
81
|
+
const server = createServer({
|
|
82
|
+
domain: 'tunnel.example.com', // Optional: custom domain
|
|
83
|
+
secure: false, // Optional: require HTTPS
|
|
84
|
+
landing: 'https://example.com', // Optional: landing page URL
|
|
85
|
+
max_tcp_sockets: 10, // Optional: max sockets per client
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
server.listen(3000, () => {
|
|
89
|
+
console.log('pipenet server listening on port 3000');
|
|
90
|
+
});
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### Server Options
|
|
94
|
+
|
|
95
|
+
- `domain` (string) Custom domain for the tunnel server
|
|
96
|
+
- `secure` (boolean) Require HTTPS connections
|
|
97
|
+
- `landing` (string) URL to redirect root requests to
|
|
98
|
+
- `max_tcp_sockets` (number) Maximum number of TCP sockets per client (default: 10)
|
|
99
|
+
|
|
100
|
+
### Server API Endpoints
|
|
101
|
+
|
|
102
|
+
- `GET /api/status` - Server status and tunnel count
|
|
103
|
+
- `GET /api/tunnels/:id/status` - Status of a specific tunnel
|
|
104
|
+
- `GET /:id` - Request a new tunnel with the specified ID
|
|
105
|
+
|
|
106
|
+
## Acknowledgments
|
|
107
|
+
|
|
108
|
+
pipenet is based on [localtunnel](https://github.com/localtunnel/localtunnel), an open-source project by [@defunctzombie](https://github.com/defunctzombie). We are grateful for the foundation it provided.
|
|
109
|
+
|
|
110
|
+
Development of pipenet is sponsored by [glama.ai](https://glama.ai).
|
|
111
|
+
|
|
112
|
+
## License
|
|
113
|
+
|
|
114
|
+
MIT
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Transform, TransformCallback, TransformOptions } from 'stream';
|
|
2
|
+
export interface HeaderHostTransformerOptions extends TransformOptions {
|
|
3
|
+
host?: string;
|
|
4
|
+
}
|
|
5
|
+
export declare class HeaderHostTransformer extends Transform {
|
|
6
|
+
private host;
|
|
7
|
+
private replaced;
|
|
8
|
+
constructor(opts?: HeaderHostTransformerOptions);
|
|
9
|
+
_transform(data: Buffer, encoding: BufferEncoding, callback: TransformCallback): void;
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=HeaderHostTransformer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HeaderHostTransformer.d.ts","sourceRoot":"","sources":["../src/HeaderHostTransformer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,QAAQ,CAAC;AAExE,MAAM,WAAW,4BAA6B,SAAQ,gBAAgB;IACpE,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,qBAAa,qBAAsB,SAAQ,SAAS;IAClD,OAAO,CAAC,IAAI,CAAS;IACrB,OAAO,CAAC,QAAQ,CAAU;gBAEd,IAAI,GAAE,4BAAiC;IAMnD,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,cAAc,EAAE,QAAQ,EAAE,iBAAiB,GAAG,IAAI;CAWtF"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { Transform } from 'stream';
|
|
2
|
+
export class HeaderHostTransformer extends Transform {
|
|
3
|
+
host;
|
|
4
|
+
replaced;
|
|
5
|
+
constructor(opts = {}) {
|
|
6
|
+
super(opts);
|
|
7
|
+
this.host = opts.host || 'localhost';
|
|
8
|
+
this.replaced = false;
|
|
9
|
+
}
|
|
10
|
+
_transform(data, encoding, callback) {
|
|
11
|
+
callback(null, this.replaced
|
|
12
|
+
? data
|
|
13
|
+
: data.toString().replace(/(\r\n[Hh]ost: )\S+/, (match, $1) => {
|
|
14
|
+
this.replaced = true;
|
|
15
|
+
return $1 + this.host;
|
|
16
|
+
}));
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=HeaderHostTransformer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HeaderHostTransformer.js","sourceRoot":"","sources":["../src/HeaderHostTransformer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAuC,MAAM,QAAQ,CAAC;AAMxE,MAAM,OAAO,qBAAsB,SAAQ,SAAS;IAC1C,IAAI,CAAS;IACb,QAAQ,CAAU;IAE1B,YAAY,OAAqC,EAAE;QACjD,KAAK,CAAC,IAAI,CAAC,CAAC;QACZ,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,WAAW,CAAC;QACrC,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC;IACxB,CAAC;IAED,UAAU,CAAC,IAAY,EAAE,QAAwB,EAAE,QAA2B;QAC5E,QAAQ,CACN,IAAI,EACJ,IAAI,CAAC,QAAQ;YACX,CAAC,CAAC,IAAI;YACN,CAAC,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,oBAAoB,EAAE,CAAC,KAAK,EAAE,EAAU,EAAE,EAAE;gBAClE,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;gBACrB,OAAO,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC;YACxB,CAAC,CAAC,CACP,CAAC;IACJ,CAAC;CACF"}
|
package/dist/Tunnel.d.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { EventEmitter } from 'events';
|
|
2
|
+
import { TunnelCluster } from './TunnelCluster.js';
|
|
3
|
+
export interface TunnelOptions {
|
|
4
|
+
port?: number;
|
|
5
|
+
host?: string;
|
|
6
|
+
subdomain?: string;
|
|
7
|
+
local_host?: string;
|
|
8
|
+
local_https?: boolean;
|
|
9
|
+
local_cert?: string;
|
|
10
|
+
local_key?: string;
|
|
11
|
+
local_ca?: string;
|
|
12
|
+
allow_invalid_cert?: boolean;
|
|
13
|
+
headers?: Record<string, string>;
|
|
14
|
+
}
|
|
15
|
+
export declare class Tunnel extends EventEmitter {
|
|
16
|
+
opts: TunnelOptions;
|
|
17
|
+
closed: boolean;
|
|
18
|
+
clientId?: string;
|
|
19
|
+
url?: string;
|
|
20
|
+
cachedUrl?: string;
|
|
21
|
+
tunnelCluster?: TunnelCluster;
|
|
22
|
+
constructor(opts?: TunnelOptions);
|
|
23
|
+
private _getInfo;
|
|
24
|
+
private _init;
|
|
25
|
+
private _establish;
|
|
26
|
+
open(cb: (err?: Error) => void): void;
|
|
27
|
+
close(): void;
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=Tunnel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Tunnel.d.ts","sourceRoot":"","sources":["../src/Tunnel.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAItC,OAAO,EAAE,aAAa,EAAwB,MAAM,oBAAoB,CAAC;AAIzE,MAAM,WAAW,aAAa;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC;AA6BD,qBAAa,MAAO,SAAQ,YAAY;IAC/B,IAAI,EAAE,aAAa,CAAC;IACpB,MAAM,EAAE,OAAO,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,aAAa,CAAC;gBAEzB,IAAI,GAAE,aAAkB;IASpC,OAAO,CAAC,QAAQ;IAuBhB,OAAO,CAAC,KAAK;IAoCb,OAAO,CAAC,UAAU;IAqDlB,IAAI,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,EAAE,KAAK,KAAK,IAAI,GAAG,IAAI;IAmBrC,KAAK,IAAI,IAAI;CAId"}
|
package/dist/Tunnel.js
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { EventEmitter } from 'events';
|
|
2
|
+
import axios from 'axios';
|
|
3
|
+
import debug from 'debug';
|
|
4
|
+
import { TunnelCluster } from './TunnelCluster.js';
|
|
5
|
+
const log = debug('pipenet:client');
|
|
6
|
+
export class Tunnel extends EventEmitter {
|
|
7
|
+
opts;
|
|
8
|
+
closed;
|
|
9
|
+
clientId;
|
|
10
|
+
url;
|
|
11
|
+
cachedUrl;
|
|
12
|
+
tunnelCluster;
|
|
13
|
+
constructor(opts = {}) {
|
|
14
|
+
super();
|
|
15
|
+
this.opts = opts;
|
|
16
|
+
this.closed = false;
|
|
17
|
+
if (!this.opts.host) {
|
|
18
|
+
this.opts.host = 'https://pipenet.me';
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
_getInfo(body) {
|
|
22
|
+
const { id, ip, port, url, cached_url, max_conn_count } = body;
|
|
23
|
+
const { host, port: local_port, local_host } = this.opts;
|
|
24
|
+
const { local_https, local_cert, local_key, local_ca, allow_invalid_cert } = this.opts;
|
|
25
|
+
return {
|
|
26
|
+
name: id,
|
|
27
|
+
url,
|
|
28
|
+
cached_url,
|
|
29
|
+
max_conn: max_conn_count || 1,
|
|
30
|
+
remote_host: new URL(host).hostname,
|
|
31
|
+
remote_ip: ip,
|
|
32
|
+
remote_port: port,
|
|
33
|
+
local_port,
|
|
34
|
+
local_host,
|
|
35
|
+
local_https,
|
|
36
|
+
local_cert,
|
|
37
|
+
local_key,
|
|
38
|
+
local_ca,
|
|
39
|
+
allow_invalid_cert,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
_init(cb) {
|
|
43
|
+
const opt = this.opts;
|
|
44
|
+
const getInfo = this._getInfo.bind(this);
|
|
45
|
+
const params = {
|
|
46
|
+
responseType: 'json',
|
|
47
|
+
headers: opt.headers || {},
|
|
48
|
+
};
|
|
49
|
+
const baseUri = `${opt.host}/`;
|
|
50
|
+
const assignedDomain = opt.subdomain;
|
|
51
|
+
const uri = baseUri + (assignedDomain || '?new');
|
|
52
|
+
const getUrl = () => {
|
|
53
|
+
axios
|
|
54
|
+
.get(uri, params)
|
|
55
|
+
.then((res) => {
|
|
56
|
+
const body = res.data;
|
|
57
|
+
log('got tunnel information', res.data);
|
|
58
|
+
if (res.status !== 200) {
|
|
59
|
+
const err = new Error(body?.message || 'pipenet server returned an error, please try again');
|
|
60
|
+
return cb(err);
|
|
61
|
+
}
|
|
62
|
+
cb(null, getInfo(body));
|
|
63
|
+
})
|
|
64
|
+
.catch((err) => {
|
|
65
|
+
log(`tunnel server offline: ${err.message}, retry 1s`);
|
|
66
|
+
setTimeout(getUrl, 1000);
|
|
67
|
+
});
|
|
68
|
+
};
|
|
69
|
+
getUrl();
|
|
70
|
+
}
|
|
71
|
+
_establish(info) {
|
|
72
|
+
this.setMaxListeners(info.max_conn + (EventEmitter.defaultMaxListeners || 10));
|
|
73
|
+
this.tunnelCluster = new TunnelCluster(info);
|
|
74
|
+
this.tunnelCluster.once('open', () => {
|
|
75
|
+
this.emit('url', info.url);
|
|
76
|
+
});
|
|
77
|
+
this.tunnelCluster.on('error', (err) => {
|
|
78
|
+
log('got socket error', err.message);
|
|
79
|
+
this.emit('error', err);
|
|
80
|
+
});
|
|
81
|
+
let tunnelCount = 0;
|
|
82
|
+
this.tunnelCluster.on('open', (tunnel) => {
|
|
83
|
+
tunnelCount++;
|
|
84
|
+
log('tunnel open [total: %d]', tunnelCount);
|
|
85
|
+
const closeHandler = () => {
|
|
86
|
+
tunnel.destroy();
|
|
87
|
+
};
|
|
88
|
+
if (this.closed) {
|
|
89
|
+
closeHandler();
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
this.once('close', closeHandler);
|
|
93
|
+
tunnel.once('close', () => {
|
|
94
|
+
this.removeListener('close', closeHandler);
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
this.tunnelCluster.on('dead', () => {
|
|
98
|
+
tunnelCount--;
|
|
99
|
+
log('tunnel dead [total: %d]', tunnelCount);
|
|
100
|
+
if (this.closed) {
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
this.tunnelCluster.open();
|
|
104
|
+
});
|
|
105
|
+
this.tunnelCluster.on('request', (req) => {
|
|
106
|
+
this.emit('request', req);
|
|
107
|
+
});
|
|
108
|
+
for (let count = 0; count < info.max_conn; ++count) {
|
|
109
|
+
this.tunnelCluster.open();
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
open(cb) {
|
|
113
|
+
this._init((err, info) => {
|
|
114
|
+
if (err) {
|
|
115
|
+
cb(err);
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
this.clientId = info.name;
|
|
119
|
+
this.url = info.url;
|
|
120
|
+
if (info.cached_url) {
|
|
121
|
+
this.cachedUrl = info.cached_url;
|
|
122
|
+
}
|
|
123
|
+
this._establish(info);
|
|
124
|
+
cb();
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
close() {
|
|
128
|
+
this.closed = true;
|
|
129
|
+
this.emit('close');
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
//# sourceMappingURL=Tunnel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Tunnel.js","sourceRoot":"","sources":["../src/Tunnel.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { EventEmitter } from 'events';
|
|
2
|
+
export interface TunnelClusterOptions {
|
|
3
|
+
name?: string;
|
|
4
|
+
url?: string;
|
|
5
|
+
cached_url?: string;
|
|
6
|
+
max_conn?: number;
|
|
7
|
+
remote_host?: string;
|
|
8
|
+
remote_ip?: string;
|
|
9
|
+
remote_port?: number;
|
|
10
|
+
local_port?: number;
|
|
11
|
+
local_host?: string;
|
|
12
|
+
local_https?: boolean;
|
|
13
|
+
local_cert?: string;
|
|
14
|
+
local_key?: string;
|
|
15
|
+
local_ca?: string;
|
|
16
|
+
allow_invalid_cert?: boolean;
|
|
17
|
+
}
|
|
18
|
+
export interface TunnelRequest {
|
|
19
|
+
method: string;
|
|
20
|
+
path: string;
|
|
21
|
+
}
|
|
22
|
+
export declare class TunnelCluster extends EventEmitter {
|
|
23
|
+
private opts;
|
|
24
|
+
constructor(opts?: TunnelClusterOptions);
|
|
25
|
+
open(): void;
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=TunnelCluster.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TunnelCluster.d.ts","sourceRoot":"","sources":["../src/TunnelCluster.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAUtC,MAAM,WAAW,oBAAoB;IACnC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;CACd;AAED,qBAAa,aAAc,SAAQ,YAAY;IAC7C,OAAO,CAAC,IAAI,CAAuB;gBAEvB,IAAI,GAAE,oBAAyB;IAK3C,IAAI,IAAI,IAAI;CA4Hb"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { EventEmitter } from 'events';
|
|
2
|
+
import debug from 'debug';
|
|
3
|
+
import fs from 'fs';
|
|
4
|
+
import net from 'net';
|
|
5
|
+
import tls from 'tls';
|
|
6
|
+
import { HeaderHostTransformer } from './HeaderHostTransformer.js';
|
|
7
|
+
const log = debug('pipenet:client');
|
|
8
|
+
export class TunnelCluster extends EventEmitter {
|
|
9
|
+
opts;
|
|
10
|
+
constructor(opts = {}) {
|
|
11
|
+
super();
|
|
12
|
+
this.opts = opts;
|
|
13
|
+
}
|
|
14
|
+
open() {
|
|
15
|
+
const opt = this.opts;
|
|
16
|
+
const remoteHostOrIp = opt.remote_ip || opt.remote_host;
|
|
17
|
+
const remotePort = opt.remote_port;
|
|
18
|
+
const localHost = opt.local_host || 'localhost';
|
|
19
|
+
const localPort = opt.local_port;
|
|
20
|
+
const localProtocol = opt.local_https ? 'https' : 'http';
|
|
21
|
+
const allowInvalidCert = opt.allow_invalid_cert;
|
|
22
|
+
log('establishing tunnel %s://%s:%s <> %s:%s', localProtocol, localHost, localPort, remoteHostOrIp, remotePort);
|
|
23
|
+
const remote = net.connect({
|
|
24
|
+
host: remoteHostOrIp,
|
|
25
|
+
port: remotePort,
|
|
26
|
+
});
|
|
27
|
+
remote.setKeepAlive(true);
|
|
28
|
+
remote.on('error', (err) => {
|
|
29
|
+
log('got remote connection error', err.message);
|
|
30
|
+
if (err.code === 'ECONNREFUSED') {
|
|
31
|
+
this.emit('error', new Error(`connection refused: ${remoteHostOrIp}:${remotePort} (check your firewall settings)`));
|
|
32
|
+
}
|
|
33
|
+
remote.end();
|
|
34
|
+
});
|
|
35
|
+
const connLocal = () => {
|
|
36
|
+
if (remote.destroyed) {
|
|
37
|
+
log('remote destroyed');
|
|
38
|
+
this.emit('dead');
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
log('connecting locally to %s://%s:%d', localProtocol, localHost, localPort);
|
|
42
|
+
remote.pause();
|
|
43
|
+
if (allowInvalidCert) {
|
|
44
|
+
log('allowing invalid certificates');
|
|
45
|
+
}
|
|
46
|
+
const getLocalCertOpts = () => allowInvalidCert
|
|
47
|
+
? { rejectUnauthorized: false }
|
|
48
|
+
: {
|
|
49
|
+
cert: fs.readFileSync(opt.local_cert),
|
|
50
|
+
key: fs.readFileSync(opt.local_key),
|
|
51
|
+
ca: opt.local_ca ? [fs.readFileSync(opt.local_ca)] : undefined,
|
|
52
|
+
};
|
|
53
|
+
const local = opt.local_https
|
|
54
|
+
? tls.connect({ host: localHost, port: localPort, ...getLocalCertOpts() })
|
|
55
|
+
: net.connect({ host: localHost, port: localPort });
|
|
56
|
+
const remoteClose = () => {
|
|
57
|
+
log('remote close');
|
|
58
|
+
this.emit('dead');
|
|
59
|
+
local.end();
|
|
60
|
+
};
|
|
61
|
+
remote.once('close', remoteClose);
|
|
62
|
+
local.once('error', (err) => {
|
|
63
|
+
log('local error %s', err.message);
|
|
64
|
+
local.end();
|
|
65
|
+
remote.removeListener('close', remoteClose);
|
|
66
|
+
if (err.code !== 'ECONNREFUSED' && err.code !== 'ECONNRESET') {
|
|
67
|
+
remote.end();
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
setTimeout(connLocal, 1000);
|
|
71
|
+
});
|
|
72
|
+
local.once('connect', () => {
|
|
73
|
+
log('connected locally');
|
|
74
|
+
remote.resume();
|
|
75
|
+
let stream = remote;
|
|
76
|
+
if (opt.local_host) {
|
|
77
|
+
log('transform Host header to %s', opt.local_host);
|
|
78
|
+
stream = remote.pipe(new HeaderHostTransformer({ host: opt.local_host }));
|
|
79
|
+
}
|
|
80
|
+
stream.pipe(local).pipe(remote);
|
|
81
|
+
local.once('close', (hadError) => {
|
|
82
|
+
log('local connection closed [%s]', hadError);
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
};
|
|
86
|
+
remote.on('data', (data) => {
|
|
87
|
+
const match = data.toString().match(/^(\w+) (\S+)/);
|
|
88
|
+
if (match) {
|
|
89
|
+
this.emit('request', {
|
|
90
|
+
method: match[1],
|
|
91
|
+
path: match[2],
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
remote.once('connect', () => {
|
|
96
|
+
this.emit('open', remote);
|
|
97
|
+
connLocal();
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=TunnelCluster.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TunnelCluster.js","sourceRoot":"","sources":["../src/TunnelCluster.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,GAAG,MAAM,KAAK,CAAC;AACtB,OAAO,GAAG,MAAM,KAAK,CAAC;AAEtB,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AAEnE,MAAM,GAAG,GAAG,KAAK,CAAC,gBAAgB,CAAC,CAAC;AAwBpC,MAAM,OAAO,aAAc,SAAQ,YAAY;IACrC,IAAI,CAAuB;IAEnC,YAAY,OAA6B,EAAE;QACzC,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;IAED,IAAI;QACF,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC;QAEtB,MAAM,cAAc,GAAG,GAAG,CAAC,SAAS,IAAI,GAAG,CAAC,WAAW,CAAC;QACxD,MAAM,UAAU,GAAG,GAAG,CAAC,WAAW,CAAC;QACnC,MAAM,SAAS,GAAG,GAAG,CAAC,UAAU,IAAI,WAAW,CAAC;QAChD,MAAM,SAAS,GAAG,GAAG,CAAC,UAAU,CAAC;QACjC,MAAM,aAAa,GAAG,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC;QACzD,MAAM,gBAAgB,GAAG,GAAG,CAAC,kBAAkB,CAAC;QAEhD,GAAG,CACD,yCAAyC,EACzC,aAAa,EACb,SAAS,EACT,SAAS,EACT,cAAc,EACd,UAAU,CACX,CAAC;QAEF,MAAM,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC;YACzB,IAAI,EAAE,cAAc;YACpB,IAAI,EAAE,UAAW;SAClB,CAAC,CAAC;QAEH,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;QAE1B,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAA0B,EAAE,EAAE;YAChD,GAAG,CAAC,6BAA6B,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;YAEhD,IAAI,GAAG,CAAC,IAAI,KAAK,cAAc,EAAE,CAAC;gBAChC,IAAI,CAAC,IAAI,CACP,OAAO,EACP,IAAI,KAAK,CACP,uBAAuB,cAAc,IAAI,UAAU,iCAAiC,CACrF,CACF,CAAC;YACJ,CAAC;YAED,MAAM,CAAC,GAAG,EAAE,CAAC;QACf,CAAC,CAAC,CAAC;QAEH,MAAM,SAAS,GAAG,GAAS,EAAE;YAC3B,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;gBACrB,GAAG,CAAC,kBAAkB,CAAC,CAAC;gBACxB,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;gBAClB,OAAO;YACT,CAAC;YAED,GAAG,CAAC,kCAAkC,EAAE,aAAa,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;YAC7E,MAAM,CAAC,KAAK,EAAE,CAAC;YAEf,IAAI,gBAAgB,EAAE,CAAC;gBACrB,GAAG,CAAC,+BAA+B,CAAC,CAAC;YACvC,CAAC;YAED,MAAM,gBAAgB,GAAG,GAAG,EAAE,CAC5B,gBAAgB;gBACd,CAAC,CAAC,EAAE,kBAAkB,EAAE,KAAK,EAAE;gBAC/B,CAAC,CAAC;oBACE,IAAI,EAAE,EAAE,CAAC,YAAY,CAAC,GAAG,CAAC,UAAW,CAAC;oBACtC,GAAG,EAAE,EAAE,CAAC,YAAY,CAAC,GAAG,CAAC,SAAU,CAAC;oBACpC,EAAE,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,YAAY,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS;iBAC/D,CAAC;YAER,MAAM,KAAK,GAAG,GAAG,CAAC,WAAW;gBAC3B,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,SAAU,EAAE,GAAG,gBAAgB,EAAE,EAAE,CAAC;gBAC3E,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,SAAU,EAAE,CAAC,CAAC;YAEvD,MAAM,WAAW,GAAG,GAAS,EAAE;gBAC7B,GAAG,CAAC,cAAc,CAAC,CAAC;gBACpB,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;gBAClB,KAAK,CAAC,GAAG,EAAE,CAAC;YACd,CAAC,CAAC;YAEF,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;YAElC,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,GAA0B,EAAE,EAAE;gBACjD,GAAG,CAAC,gBAAgB,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;gBACnC,KAAK,CAAC,GAAG,EAAE,CAAC;gBAEZ,MAAM,CAAC,cAAc,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;gBAE5C,IAAI,GAAG,CAAC,IAAI,KAAK,cAAc,IAAI,GAAG,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;oBAC7D,MAAM,CAAC,GAAG,EAAE,CAAC;oBACb,OAAO;gBACT,CAAC;gBAED,UAAU,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;YAC9B,CAAC,CAAC,CAAC;YAEH,KAAK,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,EAAE;gBACzB,GAAG,CAAC,mBAAmB,CAAC,CAAC;gBACzB,MAAM,CAAC,MAAM,EAAE,CAAC;gBAEhB,IAAI,MAAM,GAA0B,MAAM,CAAC;gBAE3C,IAAI,GAAG,CAAC,UAAU,EAAE,CAAC;oBACnB,GAAG,CAAC,6BAA6B,EAAE,GAAG,CAAC,UAAU,CAAC,CAAC;oBACnD,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,qBAAqB,CAAC,EAAE,IAAI,EAAE,GAAG,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC;gBAC5E,CAAC;gBAED,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;gBAEhC,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,QAAiB,EAAE,EAAE;oBACxC,GAAG,CAAC,8BAA8B,EAAE,QAAQ,CAAC,CAAC;gBAChD,CAAC,CAAC,CAAC;YACL,CAAC,CAAC,CAAC;QACL,CAAC,CAAC;QAEF,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAY,EAAE,EAAE;YACjC,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;YACpD,IAAI,KAAK,EAAE,CAAC;gBACV,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE;oBACnB,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC;oBAChB,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC;iBACE,CAAC,CAAC;YACtB,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,EAAE;YAC1B,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;YAC1B,SAAS,EAAE,CAAC;QACd,CAAC,CAAC,CAAC;IACL,CAAC;CACF"}
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
|