@opentunnel/client 0.1.1 → 0.2.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/package.json +3 -3
- package/src/effect/api.ts +2 -2
- package/src/effect/client.ts +11 -11
- package/src/effect/errors.ts +4 -4
- package/src/promise/client.ts +2 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opentunnel/client",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "OpenTunnel SDK for Bun: expose local services through a blind TLS tunnel",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -28,8 +28,8 @@
|
|
|
28
28
|
"test": "bun test"
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@opentunnel/protocol": "0.
|
|
32
|
-
"effect": "4.0.0-
|
|
31
|
+
"@opentunnel/protocol": "0.2.0",
|
|
32
|
+
"effect": "4.0.0-rc.112"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
35
|
"@peculiar/x509": "2.0.0",
|
package/src/effect/api.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Effect, Layer,
|
|
1
|
+
import { Effect, Layer, Context } from "effect";
|
|
2
2
|
import { FetchHttpClient, HttpClient, HttpClientRequest } from "effect/unstable/http";
|
|
3
3
|
import { HttpApiClient } from "effect/unstable/httpapi";
|
|
4
4
|
import { Api } from "@opentunnel/protocol/api/api";
|
|
@@ -11,7 +11,7 @@ interface OpenTunnelApi {
|
|
|
11
11
|
readonly authorized: (token: Tunnel.Token) => Effect.Effect<Client>;
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
export class OpenTunnelApiClient extends
|
|
14
|
+
export class OpenTunnelApiClient extends Context.Service<OpenTunnelApiClient, OpenTunnelApi>()(
|
|
15
15
|
"@opentunnel/client/OpenTunnelApiClient",
|
|
16
16
|
) {
|
|
17
17
|
static layer(options: { readonly api: URL | string }) {
|
package/src/effect/client.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Cause, Effect, Layer, Queue,
|
|
1
|
+
import { Cause, Effect, Layer, Queue, Context, Stream } from "effect";
|
|
2
2
|
import { CSR } from "@opentunnel/protocol/csr";
|
|
3
3
|
import { Tunnel } from "@opentunnel/protocol/tunnel";
|
|
4
4
|
import { OpenTunnelApiClient } from "./api.js";
|
|
@@ -33,7 +33,7 @@ export interface OpenTunnelClientOptions {
|
|
|
33
33
|
readonly storage?: Storage;
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
export class OpenTunnelClient extends
|
|
36
|
+
export class OpenTunnelClient extends Context.Service<
|
|
37
37
|
OpenTunnelClient,
|
|
38
38
|
OpenTunnelEffectClient
|
|
39
39
|
>()("@opentunnel/client/OpenTunnelClient") {
|
|
@@ -56,10 +56,10 @@ export class OpenTunnelClient extends ServiceMap.Service<
|
|
|
56
56
|
readonly pending: OpenTunnelPendingIdentity;
|
|
57
57
|
readonly onProgress?: (stage: OpenTunnelProvisionStage) => void;
|
|
58
58
|
}) {
|
|
59
|
-
const authorized = yield* api.authorized(Tunnel.Token.
|
|
59
|
+
const authorized = yield* api.authorized(Tunnel.Token.make(options.pending.token));
|
|
60
60
|
yield* Effect.sync(() => options.onProgress?.("requesting-certificate"));
|
|
61
61
|
yield* authorized.tunnel["tunnel.bindCertificate"]({
|
|
62
|
-
params: { id: Tunnel.ID.
|
|
62
|
+
params: { id: Tunnel.ID.make(options.pending.id) },
|
|
63
63
|
payload: { csr: options.pending.csr as CSR.Raw },
|
|
64
64
|
}).pipe(
|
|
65
65
|
// A resumed provision may already have an issuance in flight.
|
|
@@ -71,7 +71,7 @@ export class OpenTunnelClient extends ServiceMap.Service<
|
|
|
71
71
|
while (true) {
|
|
72
72
|
yield* Effect.sync(() => options.onProgress?.("waiting-certificate"));
|
|
73
73
|
const value = yield* authorized.tunnel["tunnel.getCertificate"]({
|
|
74
|
-
params: { id: Tunnel.ID.
|
|
74
|
+
params: { id: Tunnel.ID.make(options.pending.id) },
|
|
75
75
|
}).pipe(
|
|
76
76
|
Effect.mapError((cause) => clientError("Failed to read certificate", cause)),
|
|
77
77
|
);
|
|
@@ -176,9 +176,9 @@ export class OpenTunnelClient extends ServiceMap.Service<
|
|
|
176
176
|
) {
|
|
177
177
|
const existing = yield* get(input);
|
|
178
178
|
if (!existing) return yield* create(input);
|
|
179
|
-
const authorized = yield* api.authorized(Tunnel.Token.
|
|
179
|
+
const authorized = yield* api.authorized(Tunnel.Token.make(existing.token));
|
|
180
180
|
const certificate = yield* authorized.tunnel["tunnel.getCertificate"]({
|
|
181
|
-
params: { id: Tunnel.ID.
|
|
181
|
+
params: { id: Tunnel.ID.make(existing.id) },
|
|
182
182
|
}).pipe(
|
|
183
183
|
Effect.mapError((cause) => clientError("Failed to read certificate", cause)),
|
|
184
184
|
);
|
|
@@ -197,9 +197,9 @@ export class OpenTunnelClient extends ServiceMap.Service<
|
|
|
197
197
|
if (state.type !== "failed") return existing;
|
|
198
198
|
return yield* provision({
|
|
199
199
|
profile: profileName(input),
|
|
200
|
-
id: Tunnel.ID.
|
|
200
|
+
id: Tunnel.ID.make(existing.id),
|
|
201
201
|
hostname: existing.hostname,
|
|
202
|
-
token: Tunnel.Token.
|
|
202
|
+
token: Tunnel.Token.make(existing.token),
|
|
203
203
|
});
|
|
204
204
|
});
|
|
205
205
|
|
|
@@ -235,9 +235,9 @@ export class OpenTunnelClient extends ServiceMap.Service<
|
|
|
235
235
|
const profile = profileName(input);
|
|
236
236
|
const identity = yield* storage.load(profile);
|
|
237
237
|
if (!identity) return;
|
|
238
|
-
const authorized = yield* api.authorized(Tunnel.Token.
|
|
238
|
+
const authorized = yield* api.authorized(Tunnel.Token.make(identity.token));
|
|
239
239
|
yield* authorized.tunnel["tunnel.remove"]({
|
|
240
|
-
params: { id: Tunnel.ID.
|
|
240
|
+
params: { id: Tunnel.ID.make(identity.id) },
|
|
241
241
|
}).pipe(
|
|
242
242
|
Effect.mapError((cause) => clientError("Failed to remove tunnel", cause)),
|
|
243
243
|
);
|
package/src/effect/errors.ts
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { Schema } from "effect";
|
|
2
2
|
|
|
3
|
-
export class OpenTunnelClientError extends Schema.
|
|
3
|
+
export class OpenTunnelClientError extends Schema.TaggedError<OpenTunnelClientError>()(
|
|
4
4
|
"OpenTunnelClientError",
|
|
5
|
-
{ message: Schema.String, cause: Schema.optional(Schema.Defect) },
|
|
5
|
+
{ message: Schema.String, cause: Schema.optional(Schema.Defect()) },
|
|
6
6
|
) {}
|
|
7
7
|
|
|
8
|
-
export class OpenTunnelStorageError extends Schema.
|
|
8
|
+
export class OpenTunnelStorageError extends Schema.TaggedError<OpenTunnelStorageError>()(
|
|
9
9
|
"OpenTunnelStorageError",
|
|
10
|
-
{ message: Schema.String, cause: Schema.optional(Schema.Defect) },
|
|
10
|
+
{ message: Schema.String, cause: Schema.optional(Schema.Defect()) },
|
|
11
11
|
) {}
|
|
12
12
|
|
|
13
13
|
export type OpenTunnelError = OpenTunnelClientError | OpenTunnelStorageError;
|
package/src/promise/client.ts
CHANGED
|
@@ -78,7 +78,7 @@ export function create(options: OpenTunnelClientOptions = {}): OpenTunnelPromise
|
|
|
78
78
|
const runtime = ManagedRuntime.make(OpenTunnelClient.layer(effectOptions));
|
|
79
79
|
const withClient = <A, E>(
|
|
80
80
|
f: (client: OpenTunnelClient["Service"]) => Effect.Effect<A, E>,
|
|
81
|
-
) => runtime.runPromise(Effect.flatMap(OpenTunnelClient
|
|
81
|
+
) => runtime.runPromise(Effect.flatMap(OpenTunnelClient, f));
|
|
82
82
|
|
|
83
83
|
return {
|
|
84
84
|
profile: { list: () => withClient((client) => client.profile.list()) },
|
|
@@ -95,7 +95,7 @@ export function create(options: OpenTunnelClientOptions = {}): OpenTunnelPromise
|
|
|
95
95
|
const closeScope = () => runtime.runPromise(Scope.close(scope, Exit.void));
|
|
96
96
|
const connection = await runtime
|
|
97
97
|
.runPromise(
|
|
98
|
-
Effect.flatMap(OpenTunnelClient
|
|
98
|
+
Effect.flatMap(OpenTunnelClient, (client) => client.tunnel.connect(input)).pipe(
|
|
99
99
|
Effect.provideService(Scope.Scope, scope),
|
|
100
100
|
),
|
|
101
101
|
)
|