localpreview 0.2.5 → 0.2.6
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/dist/cli-ui.d.ts.map +1 -1
- package/dist/cli-ui.js +2 -0
- package/dist/command.d.ts.map +1 -1
- package/dist/command.js +7 -5
- package/dist/config.d.ts +3 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +3 -1
- package/dist/control-plane.d.ts +3 -7
- package/dist/control-plane.d.ts.map +1 -1
- package/dist/control-plane.js +4 -2
- package/dist/relay-client.d.ts +8 -3
- package/dist/relay-client.d.ts.map +1 -1
- package/dist/relay-client.js +36 -7
- package/package.json +17 -19
package/dist/cli-ui.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli-ui.d.ts","sourceRoot":"","sources":["../src/cli-ui.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,mBAAmB,EAAkB,MAAM,wBAAwB,CAAC;AAIlF,eAAO,MAAM,eAAe,6BAA6B,CAAC;AAE1D,eAAO,MAAM,kBAAkB,GAAI,MAAK,MAAM,CAAC,UAAwB,KAAG,OAGzE,CAAC;AAEF,eAAO,MAAM,aAAa,GAAI,SAAS,MAAM,KAAG,MAQ/C,CAAC;AAEF,eAAO,MAAM,cAAc,GAAI,SAAS,MAAM,KAAG,MAQhD,CAAC;AAEF,eAAO,MAAM,YAAY,GAAI,SAAS,MAAM,KAAG,MAM9C,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAAI,SAAS,MAAM,KAAG,MACT,CAAC;AAE/C,eAAO,MAAM,qBAAqB,GAAI,QAAQ,MAAM,EAAE,MAAM,MAAM,KAAG,MASpE,CAAC;AAEF,eAAO,MAAM,6BAA6B,GAAI,QAAQ,MAAM,EAAE,WAAW,MAAM,KAAG,MAUjF,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAAI,QAAQ,MAAM,EAAE,MAAM,MAAM,EAAE,YAAY,MAAM,KAAG,MAgBvF,CAAC;AAEF,eAAO,MAAM,4BAA4B,GACvC,QAAQ,MAAM,EACd,WAAW,MAAM,EACjB,YAAY,MAAM,KACjB,MAiBF,CAAC;AAIF,eAAO,MAAM,2BAA2B,GAAI,SAAS;IACnD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B,KAAG,MAiBH,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAAI,MAAM,MAAM,EAAE,SAAS,MAAM,KAAG,MASlE,CAAC;AAEF,eAAO,MAAM,8BAA8B,GAAI,SAAS;IACtD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB,KAAG,MAaH,CAAC;AAKF,eAAO,MAAM,4BAA4B,QAAO,MAA0C,CAAC;AAE3F,eAAO,MAAM,yBAAyB,QAAO,MACkD,CAAC;AAEhG,MAAM,MAAM,iBAAiB,GAAG;IAC9B,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;CAClC,CAAC;AAiDF,eAAO,MAAM,gBAAgB,GAAI,UAAS,iBAAsB,KAAG,MASlE,CAAC;AAEF,eAAO,MAAM,iBAAiB,QAAO,MAuBjC,CAAC;AAEL,eAAO,MAAM,eAAe,GAAI,UAAS,iBAAsB,KAAG,MA+BjE,CAAC;AAEF,eAAO,MAAM,cAAc,GAAI,UAAS,iBAAsB,KAAG,MA+BhE,CAAC;
|
|
1
|
+
{"version":3,"file":"cli-ui.d.ts","sourceRoot":"","sources":["../src/cli-ui.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,mBAAmB,EAAkB,MAAM,wBAAwB,CAAC;AAIlF,eAAO,MAAM,eAAe,6BAA6B,CAAC;AAE1D,eAAO,MAAM,kBAAkB,GAAI,MAAK,MAAM,CAAC,UAAwB,KAAG,OAGzE,CAAC;AAEF,eAAO,MAAM,aAAa,GAAI,SAAS,MAAM,KAAG,MAQ/C,CAAC;AAEF,eAAO,MAAM,cAAc,GAAI,SAAS,MAAM,KAAG,MAQhD,CAAC;AAEF,eAAO,MAAM,YAAY,GAAI,SAAS,MAAM,KAAG,MAM9C,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAAI,SAAS,MAAM,KAAG,MACT,CAAC;AAE/C,eAAO,MAAM,qBAAqB,GAAI,QAAQ,MAAM,EAAE,MAAM,MAAM,KAAG,MASpE,CAAC;AAEF,eAAO,MAAM,6BAA6B,GAAI,QAAQ,MAAM,EAAE,WAAW,MAAM,KAAG,MAUjF,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAAI,QAAQ,MAAM,EAAE,MAAM,MAAM,EAAE,YAAY,MAAM,KAAG,MAgBvF,CAAC;AAEF,eAAO,MAAM,4BAA4B,GACvC,QAAQ,MAAM,EACd,WAAW,MAAM,EACjB,YAAY,MAAM,KACjB,MAiBF,CAAC;AAIF,eAAO,MAAM,2BAA2B,GAAI,SAAS;IACnD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B,KAAG,MAiBH,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAAI,MAAM,MAAM,EAAE,SAAS,MAAM,KAAG,MASlE,CAAC;AAEF,eAAO,MAAM,8BAA8B,GAAI,SAAS;IACtD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB,KAAG,MAaH,CAAC;AAKF,eAAO,MAAM,4BAA4B,QAAO,MAA0C,CAAC;AAE3F,eAAO,MAAM,yBAAyB,QAAO,MACkD,CAAC;AAEhG,MAAM,MAAM,iBAAiB,GAAG;IAC9B,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;CAClC,CAAC;AAiDF,eAAO,MAAM,gBAAgB,GAAI,UAAS,iBAAsB,KAAG,MASlE,CAAC;AAEF,eAAO,MAAM,iBAAiB,QAAO,MAuBjC,CAAC;AAEL,eAAO,MAAM,eAAe,GAAI,UAAS,iBAAsB,KAAG,MA+BjE,CAAC;AAEF,eAAO,MAAM,cAAc,GAAI,UAAS,iBAAsB,KAAG,MA+BhE,CAAC;AAcF,eAAO,MAAM,uBAAuB,GAAI,UAAU,mBAAmB,KAAG,MAkEvE,CAAC;AAyCF,eAAO,MAAM,gBAAgB,GAAI,aAAa,MAAM,GAAG,SAAS,KAAG,MA0BlE,CAAC"}
|
package/dist/cli-ui.js
CHANGED
|
@@ -238,6 +238,7 @@ export const renderListHelp = (options = {}) => {
|
|
|
238
238
|
};
|
|
239
239
|
const LIST_COLUMNS = [
|
|
240
240
|
"kind",
|
|
241
|
+
"state",
|
|
241
242
|
"subdomain",
|
|
242
243
|
"tunnel",
|
|
243
244
|
"age",
|
|
@@ -289,6 +290,7 @@ export const formatListTunnelsOutput = (response) => {
|
|
|
289
290
|
};
|
|
290
291
|
const formatListTunnelRow = (item) => [
|
|
291
292
|
formatListItemKind(item.kind),
|
|
293
|
+
item.status ?? "-",
|
|
292
294
|
item.subdomain ?? "-",
|
|
293
295
|
formatShortId(item.tunnelId),
|
|
294
296
|
formatCompactAge(item.activeForMs),
|
package/dist/command.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"command.d.ts","sourceRoot":"","sources":["../src/command.ts"],"names":[],"mappings":"AAQA,OAAO,EAAW,MAAM,EAAiB,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"command.d.ts","sourceRoot":"","sources":["../src/command.ts"],"names":[],"mappings":"AAQA,OAAO,EAAW,MAAM,EAAiB,MAAM,QAAQ,CAAC;AAuBxD,OAAO,EAAE,aAAa,EAAgB,KAAK,eAAe,EAAE,MAAM,aAAa,CAAC;AAyChF,eAAO,MAAM,MAAM,GACjB,MAAM,aAAa,CAAC,MAAM,CAAC,KAC1B,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,eAAe,GAAG,aAAa,CAmBrD,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAAI,MAAM,aAAa,CAAC,MAAM,CAAC,KAAG,aAAa,CAAC,MAAM,CAC1C,CAAC;AAE1C,eAAO,MAAM,wBAAwB,GACnC,MAAM,aAAa,CAAC,MAAM,CAAC,EAC3B,QAAQ,OAAO,KACd,aAAa,CAAC,MAAM,CAAmE,CAAC"}
|
package/dist/command.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { formatCaptureOrigin, parseCaptureHostPort, parseTarget, validateRequestedSubdomain, } from "@localpreview/protocol";
|
|
2
2
|
import { Console, Effect, Layer, Option } from "effect";
|
|
3
|
-
import { adminTokenRequiredMessage,
|
|
4
|
-
import { CliConfig, CliConfigLive, LOCAL_CONTROL_PLANE_URL, normalizeControlPlaneUrl } from "./config.js";
|
|
3
|
+
import { adminTokenRequiredMessage, formatWarning, formatListTunnelsOutput, renderCleanHelp, renderConnectHelp, renderGlobalHelp, renderListHelp, removedAdminTokenFlagMessage, } from "./cli-ui.js";
|
|
4
|
+
import { CliConfig, CliConfigLive, LOCAL_CONTROL_PLANE_PUBLIC_HOST, LOCAL_CONTROL_PLANE_URL, normalizeControlPlaneUrl, } from "./config.js";
|
|
5
5
|
import { ControlPlaneClient, ControlPlaneClientLive, } from "./control-plane.js";
|
|
6
6
|
import { CliUsageError, errorMessage } from "./errors.js";
|
|
7
7
|
import { LocalProxyLive } from "./local-proxy.js";
|
|
@@ -178,6 +178,7 @@ const parseConnectArgs = (argv) => {
|
|
|
178
178
|
config: {
|
|
179
179
|
captures,
|
|
180
180
|
controlPlane: toOption(controlPlane),
|
|
181
|
+
localMode: usedLocalControlPlane,
|
|
181
182
|
requestedName: toOption(requestedName),
|
|
182
183
|
target,
|
|
183
184
|
},
|
|
@@ -468,9 +469,10 @@ const runConnect = (config, legacy, originalArgv) => Effect.scoped(Effect.gen(fu
|
|
|
468
469
|
const controlPlane = yield* ControlPlaneClient;
|
|
469
470
|
const relay = yield* RelayClient;
|
|
470
471
|
const cliConfig = yield* CliConfig;
|
|
471
|
-
const tunnel = yield* Effect.acquireRelease(controlPlane.createTunnel(cliConfig.controlPlaneUrl,
|
|
472
|
-
|
|
473
|
-
|
|
472
|
+
const tunnel = yield* Effect.acquireRelease(controlPlane.createTunnel(cliConfig.controlPlaneUrl, {
|
|
473
|
+
...(config.localMode ? { publicHost: LOCAL_CONTROL_PLANE_PUBLIC_HOST } : {}),
|
|
474
|
+
...(requestedSubdomain === undefined ? {} : { requestedSubdomain }),
|
|
475
|
+
}), (tunnel) => closeTunnelBestEffort(controlPlane, cliConfig.controlPlaneUrl, tunnel));
|
|
474
476
|
if (config.captures.length > 0) {
|
|
475
477
|
const origins = config.captures.map((capture) => formatCaptureOrigin(capture)).join(", ");
|
|
476
478
|
yield* Console.error(formatWarning(`Captured local backends (${origins}) are exposed through this preview URL. Anyone with the link can reach them.`));
|
package/dist/config.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ export type CliConfigShape = {
|
|
|
4
4
|
readonly controlPlaneUrl: string;
|
|
5
5
|
readonly maxInFlightRequests: number;
|
|
6
6
|
readonly relayConnectTimeoutMs: number;
|
|
7
|
+
readonly relayReadyTimeoutMs: number;
|
|
7
8
|
readonly requestBodyLimitBytes: number;
|
|
8
9
|
readonly requestTimeoutMs: number;
|
|
9
10
|
readonly responseBodyLimitBytes: number;
|
|
@@ -13,7 +14,8 @@ declare const CliConfig_base: Context.ServiceClass<CliConfig, "CliConfig", CliCo
|
|
|
13
14
|
export declare class CliConfig extends CliConfig_base {
|
|
14
15
|
}
|
|
15
16
|
export declare const PUBLIC_CONTROL_PLANE_URL = "https://localpreview.dev";
|
|
16
|
-
export declare const LOCAL_CONTROL_PLANE_URL = "http://
|
|
17
|
+
export declare const LOCAL_CONTROL_PLANE_URL = "http://127.0.0.1:3000";
|
|
18
|
+
export declare const LOCAL_CONTROL_PLANE_PUBLIC_HOST = "localhost:3000";
|
|
17
19
|
export type NormalizeControlPlaneUrlResult = {
|
|
18
20
|
readonly ok: true;
|
|
19
21
|
readonly url: string;
|
package/dist/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAC;AAEhD,MAAM,MAAM,cAAc,GAAG;IAC3B,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;IACxC,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,mBAAmB,EAAE,MAAM,CAAC;IACrC,QAAQ,CAAC,qBAAqB,EAAE,MAAM,CAAC;IACvC,QAAQ,CAAC,qBAAqB,EAAE,MAAM,CAAC;IACvC,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,sBAAsB,EAAE,MAAM,CAAC;IACxC,QAAQ,CAAC,sBAAsB,EAAE,MAAM,CAAC;CACzC,CAAC;;AAEF,qBAAa,SAAU,SAAQ,cAAyD;CAAG;AAE3F,eAAO,MAAM,wBAAwB,6BAA6B,CAAC;AACnE,eAAO,MAAM,uBAAuB,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAC;AAEhD,MAAM,MAAM,cAAc,GAAG;IAC3B,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;IACxC,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,mBAAmB,EAAE,MAAM,CAAC;IACrC,QAAQ,CAAC,qBAAqB,EAAE,MAAM,CAAC;IACvC,QAAQ,CAAC,mBAAmB,EAAE,MAAM,CAAC;IACrC,QAAQ,CAAC,qBAAqB,EAAE,MAAM,CAAC;IACvC,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,sBAAsB,EAAE,MAAM,CAAC;IACxC,QAAQ,CAAC,sBAAsB,EAAE,MAAM,CAAC;CACzC,CAAC;;AAEF,qBAAa,SAAU,SAAQ,cAAyD;CAAG;AAE3F,eAAO,MAAM,wBAAwB,6BAA6B,CAAC;AACnE,eAAO,MAAM,uBAAuB,0BAA0B,CAAC;AAC/D,eAAO,MAAM,+BAA+B,mBAAmB,CAAC;AAEhE,MAAM,MAAM,8BAA8B,GACtC;IACE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAClB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACtB,GACD;IACE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;CACpB,CAAC;AAEN,gFAAgF;AAChF,eAAO,MAAM,wBAAwB,GAAI,OAAO,MAAM,KAAG,8BA4DxD,CAAC;AA2BF,eAAO,MAAM,aAAa,GAAI,OAAO;IACnC,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;CAClC,KAAG,cAmBH,CAAC;AAEF,eAAO,MAAM,aAAa,GAAI,OAAO;IACnC,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;CAClC,yCAAmD,CAAC;AAWrD,eAAO,MAAM,aAAa,GAAI,OAAO;IACnC,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;CAClC,KAAG,MAAM,CAAC,MAAM,CAAC,cAAc,CAA4C,CAAC"}
|
package/dist/config.js
CHANGED
|
@@ -3,7 +3,8 @@ import { Context, Effect, Layer } from "effect";
|
|
|
3
3
|
export class CliConfig extends Context.Service()("CliConfig") {
|
|
4
4
|
}
|
|
5
5
|
export const PUBLIC_CONTROL_PLANE_URL = LOCALPREVIEW_PUBLIC_ORIGIN;
|
|
6
|
-
export const LOCAL_CONTROL_PLANE_URL = "http://
|
|
6
|
+
export const LOCAL_CONTROL_PLANE_URL = "http://127.0.0.1:3000";
|
|
7
|
+
export const LOCAL_CONTROL_PLANE_PUBLIC_HOST = "localhost:3000";
|
|
7
8
|
/** Normalizes and validates a control-plane base URL from `--control-plane`. */
|
|
8
9
|
export const normalizeControlPlaneUrl = (value) => {
|
|
9
10
|
let parsed;
|
|
@@ -84,6 +85,7 @@ export const makeCliConfig = (input) => {
|
|
|
84
85
|
controlPlaneUrl,
|
|
85
86
|
maxInFlightRequests: readNumber(env.LOCALPREVIEW_MAX_IN_FLIGHT_REQUESTS, 100),
|
|
86
87
|
relayConnectTimeoutMs: readNumber(env.LOCALPREVIEW_RELAY_CONNECT_TIMEOUT_MS, 10_000),
|
|
88
|
+
relayReadyTimeoutMs: readNumber(env.LOCALPREVIEW_RELAY_READY_TIMEOUT_MS, 60_000),
|
|
87
89
|
requestBodyLimitBytes: readNumber(env.LOCALPREVIEW_REQUEST_BODY_LIMIT_BYTES, 10 * 1024 * 1024),
|
|
88
90
|
requestTimeoutMs: readNumber(env.LOCALPREVIEW_REQUEST_TIMEOUT_MS, 30_000),
|
|
89
91
|
responseBodyLimitBytes: readNumber(env.LOCALPREVIEW_RESPONSE_BODY_LIMIT_BYTES, 50 * 1024 * 1024),
|
package/dist/control-plane.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type CreateTunnelResponse, type ListTunnelsResponse } from "@localpreview/protocol";
|
|
1
|
+
import { type CreateTunnelRequest, type CreateTunnelResponse, type ListTunnelsResponse } from "@localpreview/protocol";
|
|
2
2
|
import { Context, Effect, Layer } from "effect";
|
|
3
3
|
import { ControlPlaneError } from "./errors.js";
|
|
4
4
|
export type ControlPlaneClientShape = {
|
|
@@ -12,9 +12,7 @@ export type ControlPlaneClientShape = {
|
|
|
12
12
|
readonly subdomain: string;
|
|
13
13
|
}) => Effect.Effect<CleanSubdomainResponse, ControlPlaneError>;
|
|
14
14
|
readonly closeTunnel: (controlPlaneUrl: string, tunnel: Pick<CreateTunnelResponse, "clientToken" | "tunnelId">) => Effect.Effect<void, ControlPlaneError>;
|
|
15
|
-
readonly createTunnel: (controlPlaneUrl: string, body:
|
|
16
|
-
readonly requestedSubdomain?: string;
|
|
17
|
-
}) => Effect.Effect<CreateTunnelResponse, ControlPlaneError>;
|
|
15
|
+
readonly createTunnel: (controlPlaneUrl: string, body: CreateTunnelRequest) => Effect.Effect<CreateTunnelResponse, ControlPlaneError>;
|
|
18
16
|
readonly listTunnels: (controlPlaneUrl: string, input: {
|
|
19
17
|
readonly adminToken: string;
|
|
20
18
|
readonly limit: number;
|
|
@@ -47,9 +45,7 @@ declare const ControlPlaneClient_base: Context.ServiceClass<ControlPlaneClient,
|
|
|
47
45
|
export declare class ControlPlaneClient extends ControlPlaneClient_base {
|
|
48
46
|
}
|
|
49
47
|
export declare const ControlPlaneClientLive: Layer.Layer<ControlPlaneClient, never, never>;
|
|
50
|
-
export declare const createTunnel: (controlPlaneUrl: string, body:
|
|
51
|
-
readonly requestedSubdomain?: string;
|
|
52
|
-
}) => Promise<CreateTunnelResponse>;
|
|
48
|
+
export declare const createTunnel: (controlPlaneUrl: string, body: CreateTunnelRequest) => Promise<CreateTunnelResponse>;
|
|
53
49
|
export declare const closeTunnel: (controlPlaneUrl: string, tunnel: Pick<CreateTunnelResponse, "clientToken" | "tunnelId">) => Promise<void>;
|
|
54
50
|
export declare const cleanSubdomain: (controlPlaneUrl: string, input: {
|
|
55
51
|
readonly adminToken: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"control-plane.d.ts","sourceRoot":"","sources":["../src/control-plane.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,oBAAoB,EACzB,KAAK,mBAAmB,EAEzB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAY,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"control-plane.d.ts","sourceRoot":"","sources":["../src/control-plane.ts"],"names":[],"mappings":"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"}
|
package/dist/control-plane.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { LOCALPREVIEW_ADMIN_TOKEN_HEADER, LOCALPREVIEW_ERROR_CODES, LOCALPREVIEW_PROTOCOL_VERSION, LOCALPREVIEW_RELAY_SNAPSHOT_VERSION, } from "@localpreview/protocol";
|
|
2
2
|
import { Context, Effect, Layer, Schedule } from "effect";
|
|
3
|
+
import { LOCAL_CONTROL_PLANE_URL } from "./config.js";
|
|
3
4
|
import { ControlPlaneError } from "./errors.js";
|
|
4
5
|
export class ControlPlaneClient extends Context.Service()("ControlPlaneClient") {
|
|
5
6
|
}
|
|
@@ -20,8 +21,9 @@ export const cleanAllSubdomains = (controlPlaneUrl, input) => Effect.runPromise(
|
|
|
20
21
|
export const listTunnels = (controlPlaneUrl, input) => Effect.runPromise(listTunnelsEffect(controlPlaneUrl, input));
|
|
21
22
|
const createTunnelEffect = (controlPlaneUrl, body) => Effect.promise(async () => {
|
|
22
23
|
let response;
|
|
24
|
+
const createTunnelUrl = new URL("/api/tunnels", controlPlaneUrl);
|
|
23
25
|
try {
|
|
24
|
-
response = await fetch(
|
|
26
|
+
response = await fetch(createTunnelUrl, {
|
|
25
27
|
body: JSON.stringify(body),
|
|
26
28
|
headers: {
|
|
27
29
|
"content-type": "application/json",
|
|
@@ -33,7 +35,7 @@ const createTunnelEffect = (controlPlaneUrl, body) => Effect.promise(async () =>
|
|
|
33
35
|
throw new ControlPlaneError({
|
|
34
36
|
message: [
|
|
35
37
|
`Could not reach localpreview control-plane at ${controlPlaneUrl}.`,
|
|
36
|
-
|
|
38
|
+
`Use "-l" or "--local" as shorthand for --control-plane ${LOCAL_CONTROL_PLANE_URL}.`,
|
|
37
39
|
].join("\n"),
|
|
38
40
|
retryable: false,
|
|
39
41
|
});
|
package/dist/relay-client.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type
|
|
2
|
-
import { Context, Effect, Layer } from "effect";
|
|
1
|
+
import { type CaptureTarget, type CreateTunnelResponse, type TunnelTarget } from "@localpreview/protocol";
|
|
2
|
+
import { Context, Deferred, Effect, Layer } from "effect";
|
|
3
3
|
import { CliConfig } from "./config.js";
|
|
4
4
|
import { RelayConnectionError, RelayProtocolError } from "./errors.js";
|
|
5
5
|
import { LocalProxy } from "./local-proxy.js";
|
|
@@ -13,7 +13,12 @@ export type RelaySessionMetadata = {
|
|
|
13
13
|
declare const RelayClient_base: Context.ServiceClass<RelayClient, "RelayClient", RelayClientShape>;
|
|
14
14
|
export declare class RelayClient extends RelayClient_base {
|
|
15
15
|
}
|
|
16
|
-
export declare const RelayClientLive: Layer.Layer<RelayClient, never,
|
|
16
|
+
export declare const RelayClientLive: Layer.Layer<RelayClient, never, CliConfig | LocalProxy>;
|
|
17
|
+
export declare const waitForTunnelReady: (input: {
|
|
18
|
+
readonly ready: Deferred.Deferred<void, RelayConnectionError>;
|
|
19
|
+
readonly terminatedBeforeReady: Deferred.Deferred<void, RelayConnectionError>;
|
|
20
|
+
readonly timeoutMs: number;
|
|
21
|
+
}) => Effect.Effect<void, RelayConnectionError>;
|
|
17
22
|
export declare const isRetryableCloseCode: (code: number) => boolean;
|
|
18
23
|
export {};
|
|
19
24
|
//# sourceMappingURL=relay-client.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"relay-client.d.ts","sourceRoot":"","sources":["../src/relay-client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"relay-client.d.ts","sourceRoot":"","sources":["../src/relay-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAA4B,KAAK,aAAa,EAAE,KAAK,oBAAoB,EAAE,KAAK,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACpI,OAAO,EAAW,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAY,MAAM,QAAQ,CAAC;AAG7E,OAAO,EAAE,SAAS,EAAuB,MAAM,aAAa,CAAC;AAC7D,OAAO,EAAE,oBAAoB,EAAE,kBAAkB,EAAgB,MAAM,aAAa,CAAC;AACrF,OAAO,EAAE,UAAU,EAAwB,MAAM,kBAAkB,CAAC;AAEpE,MAAM,MAAM,gBAAgB,GAAG;IAC7B,QAAQ,CAAC,eAAe,EAAE,CACxB,MAAM,EAAE,oBAAoB,EAC5B,MAAM,EAAE,YAAY,EACpB,QAAQ,EAAE,aAAa,CAAC,aAAa,CAAC,EACtC,eAAe,EAAE,oBAAoB,KAClC,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,oBAAoB,GAAG,kBAAkB,CAAC,CAAC;CACrE,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,YAAY,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;CAC9C,CAAC;;AAEF,qBAAa,WAAY,SAAQ,gBAA+D;CAAG;AAEnG,eAAO,MAAM,eAAe,yDAU3B,CAAC;AA0OF,eAAO,MAAM,kBAAkB,GAAI,OAAO;IACxC,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE,oBAAoB,CAAC,CAAC;IAC9D,QAAQ,CAAC,qBAAqB,EAAE,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE,oBAAoB,CAAC,CAAC;IAC9E,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B,KAAG,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,oBAAoB,CAczC,CAAC;AAEJ,eAAO,MAAM,oBAAoB,GAAI,MAAM,MAAM,KAAG,OAAwB,CAAC"}
|
package/dist/relay-client.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { decodeServerRelayMessage } from "@localpreview/protocol";
|
|
1
2
|
import { Console, Context, Deferred, Effect, Layer, Schedule } from "effect";
|
|
2
3
|
import WebSocket from "ws";
|
|
3
4
|
import { formatRelayReconnect, formatStatus } from "./cli-ui.js";
|
|
@@ -33,6 +34,9 @@ const serveOnce = (config, localProxy, tunnel, target, captures, sessionMetadata
|
|
|
33
34
|
target,
|
|
34
35
|
};
|
|
35
36
|
const done = yield* Deferred.make();
|
|
37
|
+
const ready = yield* Deferred.make();
|
|
38
|
+
const terminatedBeforeReady = yield* Deferred.make();
|
|
39
|
+
let tunnelReady = false;
|
|
36
40
|
const handleSignal = () => {
|
|
37
41
|
socket.close(1000, "Interrupted");
|
|
38
42
|
Effect.runFork(Deferred.succeed(done, undefined));
|
|
@@ -42,6 +46,14 @@ const serveOnce = (config, localProxy, tunnel, target, captures, sessionMetadata
|
|
|
42
46
|
process.once("SIGINT", handleSignal);
|
|
43
47
|
process.once("SIGTERM", handleSignal);
|
|
44
48
|
socket.on("message", (data) => {
|
|
49
|
+
const decoded = decodeServerRelayMessage(data.toString());
|
|
50
|
+
if (decoded.ok &&
|
|
51
|
+
decoded.message.type === "tunnel-ready" &&
|
|
52
|
+
decoded.message.tunnelId === tunnel.tunnelId) {
|
|
53
|
+
tunnelReady = true;
|
|
54
|
+
Effect.runFork(Deferred.succeed(ready, undefined));
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
45
57
|
const effect = localProxy.handleMessage(socket, session, data.toString()).pipe(Effect.catch((error) => Effect.gen(function* () {
|
|
46
58
|
socket.close(1002, error.message);
|
|
47
59
|
yield* Deferred.fail(done, error);
|
|
@@ -49,19 +61,23 @@ const serveOnce = (config, localProxy, tunnel, target, captures, sessionMetadata
|
|
|
49
61
|
Effect.runFork(effect);
|
|
50
62
|
});
|
|
51
63
|
socket.on("error", (error) => {
|
|
52
|
-
|
|
64
|
+
const relayError = new RelayConnectionError({
|
|
53
65
|
message: error.message,
|
|
54
|
-
})
|
|
66
|
+
});
|
|
67
|
+
Effect.runFork(Deferred.fail(done, relayError).pipe(Effect.andThen(Deferred.fail(terminatedBeforeReady, relayError))));
|
|
55
68
|
});
|
|
56
69
|
socket.on("close", (code, reason) => {
|
|
70
|
+
const relayError = new RelayConnectionError({
|
|
71
|
+
message: tunnelReady
|
|
72
|
+
? `Relay connection closed (${code}): ${reason.toString()}`
|
|
73
|
+
: `Relay connection closed before tunnel-ready (${code}): ${reason.toString()}`,
|
|
74
|
+
retryable: isRetryableCloseCode(code),
|
|
75
|
+
});
|
|
57
76
|
if (code === 1000 || code === 1001) {
|
|
58
|
-
Effect.runFork(Deferred.succeed(done, undefined));
|
|
77
|
+
Effect.runFork(Deferred.fail(terminatedBeforeReady, relayError).pipe(Effect.andThen(Deferred.succeed(done, undefined))));
|
|
59
78
|
return;
|
|
60
79
|
}
|
|
61
|
-
Effect.runFork(Deferred.fail(done,
|
|
62
|
-
message: `Relay connection closed (${code}): ${reason.toString()}`,
|
|
63
|
-
retryable: isRetryableCloseCode(code),
|
|
64
|
-
})));
|
|
80
|
+
Effect.runFork(Deferred.fail(done, relayError).pipe(Effect.andThen(Deferred.fail(terminatedBeforeReady, relayError))));
|
|
65
81
|
});
|
|
66
82
|
}), () => Effect.sync(() => {
|
|
67
83
|
process.off("SIGINT", handleSignal);
|
|
@@ -70,6 +86,13 @@ const serveOnce = (config, localProxy, tunnel, target, captures, sessionMetadata
|
|
|
70
86
|
socket.close(1000, "Closing");
|
|
71
87
|
}
|
|
72
88
|
}));
|
|
89
|
+
yield* waitForTunnelReady({
|
|
90
|
+
ready,
|
|
91
|
+
terminatedBeforeReady,
|
|
92
|
+
timeoutMs: config.relayReadyTimeoutMs,
|
|
93
|
+
});
|
|
94
|
+
yield* Console.log(formatStatus(`Tunnel ready: ${tunnel.publicUrl}`));
|
|
95
|
+
yield* Console.log(formatStatus(`Forwarding to ${target.protocol}://${target.hostname}:${target.port}`));
|
|
73
96
|
yield* Deferred.await(done);
|
|
74
97
|
}));
|
|
75
98
|
});
|
|
@@ -120,4 +143,10 @@ const openSocket = (tunnel) => Effect.callback((resume) => {
|
|
|
120
143
|
}).pipe(Effect.mapError((error) => new RelayConnectionError({
|
|
121
144
|
message: errorMessage(error),
|
|
122
145
|
})));
|
|
146
|
+
export const waitForTunnelReady = (input) => Effect.raceFirst(Deferred.await(input.ready), Deferred.await(input.terminatedBeforeReady)).pipe(Effect.timeoutOrElse({
|
|
147
|
+
duration: `${input.timeoutMs} millis`,
|
|
148
|
+
orElse: () => Effect.fail(new RelayConnectionError({
|
|
149
|
+
message: "Timed out waiting for relay tunnel-ready acknowledgement.",
|
|
150
|
+
})),
|
|
151
|
+
}));
|
|
123
152
|
export const isRetryableCloseCode = (code) => code === 1006;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "localpreview",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.6",
|
|
4
4
|
"bin": {
|
|
5
5
|
"localpreview": "./dist/index.js"
|
|
6
6
|
},
|
|
@@ -10,28 +10,26 @@
|
|
|
10
10
|
"README.md"
|
|
11
11
|
],
|
|
12
12
|
"types": "./dist/index.d.ts",
|
|
13
|
-
"scripts": {
|
|
14
|
-
"build": "tsc -p tsconfig.build.json",
|
|
15
|
-
"dev": "tsx src/index.ts",
|
|
16
|
-
"lint": "oxlint .",
|
|
17
|
-
"prepack": "pnpm build",
|
|
18
|
-
"prepublishOnly": "pnpm test && pnpm typecheck && pnpm build",
|
|
19
|
-
"test": "vitest run --passWithNoTests",
|
|
20
|
-
"typecheck": "tsc -p tsconfig.json --noEmit"
|
|
21
|
-
},
|
|
22
13
|
"dependencies": {
|
|
23
14
|
"@effect/platform-node": "beta",
|
|
24
|
-
"@localpreview/protocol": "workspace:*",
|
|
25
15
|
"effect": "beta",
|
|
26
16
|
"picocolors": "^1.1.1",
|
|
27
|
-
"ws": "latest"
|
|
17
|
+
"ws": "latest",
|
|
18
|
+
"@localpreview/protocol": "0.2.3"
|
|
28
19
|
},
|
|
29
20
|
"devDependencies": {
|
|
30
|
-
"@effect/vitest": "
|
|
31
|
-
"@types/node": "
|
|
32
|
-
"@types/ws": "
|
|
33
|
-
"tsx": "
|
|
34
|
-
"typescript": "
|
|
35
|
-
"vitest": "
|
|
21
|
+
"@effect/vitest": "beta",
|
|
22
|
+
"@types/node": "latest",
|
|
23
|
+
"@types/ws": "latest",
|
|
24
|
+
"tsx": "latest",
|
|
25
|
+
"typescript": "latest",
|
|
26
|
+
"vitest": "latest"
|
|
27
|
+
},
|
|
28
|
+
"scripts": {
|
|
29
|
+
"build": "tsc -p tsconfig.build.json",
|
|
30
|
+
"dev": "tsx src/index.ts",
|
|
31
|
+
"lint": "oxlint .",
|
|
32
|
+
"test": "vitest run --passWithNoTests",
|
|
33
|
+
"typecheck": "tsc -p tsconfig.json --noEmit"
|
|
36
34
|
}
|
|
37
|
-
}
|
|
35
|
+
}
|