t3code-cli 0.4.0 → 0.5.1
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/bin.js +4 -2
- package/dist/index.js +12 -2
- package/dist/{runtime-Cq64iuZr.js → runtime-KQVRmRk-.js} +229 -174
- package/dist/src/application/layer.d.ts +2 -2
- package/dist/src/auth/layer.d.ts +4 -2
- package/dist/src/auth/local-base-dir.d.ts +7 -0
- package/dist/src/auth/local-origin.d.ts +18 -0
- package/dist/src/auth/local-token.d.ts +26 -0
- package/dist/src/auth/local.d.ts +8 -11
- package/dist/src/auth/pairing.d.ts +6 -6
- package/dist/src/auth/service.d.ts +2 -1
- package/dist/src/auth/transport.d.ts +6 -3
- package/dist/src/auth/type.d.ts +18 -0
- package/dist/src/connection/error.d.ts +8 -0
- package/dist/src/connection/layer.d.ts +3 -0
- package/dist/src/connection/node.d.ts +2 -0
- package/dist/src/connection/service.d.ts +13 -0
- package/dist/src/connection/type.d.ts +10 -0
- package/dist/src/connection.d.ts +5 -0
- package/dist/src/index.d.ts +23 -1
- package/dist/src/rpc/error.d.ts +4 -3
- package/dist/src/rpc/layer.d.ts +5 -4
- package/dist/src/runtime.d.ts +9 -2
- package/package.json +1 -1
- package/src/auth/layer.ts +17 -0
- package/src/auth/local-base-dir.ts +22 -0
- package/src/auth/local-origin.ts +62 -0
- package/src/auth/local-token.ts +302 -0
- package/src/auth/local.ts +13 -348
- package/src/auth/pairing.ts +8 -19
- package/src/auth/service.ts +2 -1
- package/src/auth/transport.ts +17 -11
- package/src/auth/type.ts +22 -0
- package/src/cli/auth.ts +2 -0
- package/src/connection/error.ts +9 -0
- package/src/connection/layer.ts +10 -0
- package/src/connection/node.ts +12 -0
- package/src/connection/service.ts +26 -0
- package/src/connection/type.ts +12 -0
- package/src/connection.ts +9 -0
- package/src/index.ts +75 -1
- package/src/rpc/error.ts +4 -11
- package/src/rpc/layer.ts +25 -15
- package/src/runtime.ts +45 -7
package/src/auth/pairing.ts
CHANGED
|
@@ -3,8 +3,7 @@ import * as Effect from "effect/Effect";
|
|
|
3
3
|
import * as Layer from "effect/Layer";
|
|
4
4
|
import { Url } from "effect/unstable/http";
|
|
5
5
|
|
|
6
|
-
import {
|
|
7
|
-
import { AuthConfigError, AuthPairingUrlError, AuthTransportError } from "./error.ts";
|
|
6
|
+
import { AuthPairingUrlError, AuthTransportError } from "./error.ts";
|
|
8
7
|
import { T3AuthTransport } from "./transport.ts";
|
|
9
8
|
import type { PairingUrl, PairResult } from "./type.ts";
|
|
10
9
|
|
|
@@ -13,32 +12,22 @@ export class T3AuthPairing extends Context.Service<
|
|
|
13
12
|
{
|
|
14
13
|
readonly pair: (
|
|
15
14
|
pairingUrl: string,
|
|
16
|
-
) => Effect.Effect<PairResult,
|
|
15
|
+
) => Effect.Effect<PairResult, AuthPairingUrlError | AuthTransportError>;
|
|
17
16
|
}
|
|
18
17
|
>()("t3cli/T3AuthPairing") {}
|
|
19
18
|
|
|
20
19
|
export const makeT3AuthPairing = Effect.fn("makeT3AuthPairing")(function* () {
|
|
21
|
-
const config = yield* T3Config;
|
|
22
20
|
const transport = yield* T3AuthTransport;
|
|
23
21
|
|
|
24
22
|
const pair = Effect.fn("T3AuthPairingLive.pair")(function* (pairingUrl: string) {
|
|
25
23
|
const parsed = yield* parsePairingUrl(pairingUrl);
|
|
26
24
|
const result = yield* transport.bootstrapBearer(parsed);
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
yield* config
|
|
34
|
-
.writeStored({ ...existing, url: parsed.baseUrl, token: result.sessionToken })
|
|
35
|
-
.pipe(
|
|
36
|
-
Effect.catchTags({
|
|
37
|
-
ConfigError: (error) =>
|
|
38
|
-
Effect.fail(new AuthConfigError({ message: "auth config failed", cause: error })),
|
|
39
|
-
}),
|
|
40
|
-
);
|
|
41
|
-
return { url: parsed.baseUrl, role: result.role, expiresAt: result.expiresAt };
|
|
25
|
+
return {
|
|
26
|
+
url: parsed.baseUrl,
|
|
27
|
+
token: result.sessionToken,
|
|
28
|
+
role: result.role,
|
|
29
|
+
expiresAt: result.expiresAt,
|
|
30
|
+
};
|
|
42
31
|
});
|
|
43
32
|
|
|
44
33
|
return { pair };
|
package/src/auth/service.ts
CHANGED
|
@@ -3,13 +3,14 @@ import type * as Effect from "effect/Effect";
|
|
|
3
3
|
|
|
4
4
|
import type { AuthSessionState, AuthWebSocketTicketResult } from "./schema.ts";
|
|
5
5
|
import type { AuthError } from "./error.ts";
|
|
6
|
-
import type { LocalAuthInput, LocalAuthResult, PairResult } from "./type.ts";
|
|
6
|
+
import type { AuthConfigInput, LocalAuthInput, LocalAuthResult, PairResult } from "./type.ts";
|
|
7
7
|
|
|
8
8
|
export class T3Auth extends Context.Service<
|
|
9
9
|
T3Auth,
|
|
10
10
|
{
|
|
11
11
|
readonly pair: (value: string) => Effect.Effect<PairResult, AuthError>;
|
|
12
12
|
readonly local: (input: LocalAuthInput) => Effect.Effect<LocalAuthResult, AuthError>;
|
|
13
|
+
readonly writeConfig: (input: AuthConfigInput) => Effect.Effect<void, AuthError>;
|
|
13
14
|
readonly status: () => Effect.Effect<AuthSessionState, AuthError>;
|
|
14
15
|
readonly issueWebSocketTicket: () => Effect.Effect<AuthWebSocketTicketResult, AuthError>;
|
|
15
16
|
}
|
package/src/auth/transport.ts
CHANGED
|
@@ -9,7 +9,6 @@ import * as Effect from "effect/Effect";
|
|
|
9
9
|
import * as Layer from "effect/Layer";
|
|
10
10
|
import { HttpClient, HttpClientError, HttpClientRequest } from "effect/unstable/http";
|
|
11
11
|
|
|
12
|
-
import type { ResolvedConfig } from "../config/service.ts";
|
|
13
12
|
import { toHttpEndpointUrl } from "../config/url.ts";
|
|
14
13
|
import { AuthTransportError } from "./error.ts";
|
|
15
14
|
import {
|
|
@@ -21,6 +20,11 @@ import {
|
|
|
21
20
|
decodeAuthWebSocketTicketResult,
|
|
22
21
|
} from "./schema.ts";
|
|
23
22
|
|
|
23
|
+
export type AuthTransportConnection = {
|
|
24
|
+
readonly url: string;
|
|
25
|
+
readonly token: string;
|
|
26
|
+
};
|
|
27
|
+
|
|
24
28
|
export class T3AuthTransport extends Context.Service<
|
|
25
29
|
T3AuthTransport,
|
|
26
30
|
{
|
|
@@ -29,10 +33,10 @@ export class T3AuthTransport extends Context.Service<
|
|
|
29
33
|
readonly credential: string;
|
|
30
34
|
}) => Effect.Effect<AuthBearerBootstrapResult, AuthTransportError>;
|
|
31
35
|
readonly getSession: (
|
|
32
|
-
|
|
36
|
+
connection: AuthTransportConnection,
|
|
33
37
|
) => Effect.Effect<AuthSessionState, AuthTransportError>;
|
|
34
38
|
readonly issueWebSocketTicket: (
|
|
35
|
-
|
|
39
|
+
connection: AuthTransportConnection,
|
|
36
40
|
) => Effect.Effect<AuthWebSocketTicketResult, AuthTransportError>;
|
|
37
41
|
}
|
|
38
42
|
>()("t3cli/T3AuthTransport") {}
|
|
@@ -91,9 +95,11 @@ const makeT3AuthTransport = Effect.fn("makeT3AuthTransport")(function* () {
|
|
|
91
95
|
} satisfies AuthBearerBootstrapResult;
|
|
92
96
|
});
|
|
93
97
|
|
|
94
|
-
const getSession = Effect.fn("AuthTransport.getSession")(function* (
|
|
95
|
-
|
|
96
|
-
|
|
98
|
+
const getSession = Effect.fn("AuthTransport.getSession")(function* (
|
|
99
|
+
connection: AuthTransportConnection,
|
|
100
|
+
) {
|
|
101
|
+
const url = yield* makeHttpEndpointUrl(connection.url, "/api/auth/session");
|
|
102
|
+
const request = HttpClientRequest.get(url).pipe(authenticatedRequest(connection));
|
|
97
103
|
const response = yield* client.execute(request).pipe(
|
|
98
104
|
Effect.catchTags({
|
|
99
105
|
HttpClientError: (error) =>
|
|
@@ -124,10 +130,10 @@ const makeT3AuthTransport = Effect.fn("makeT3AuthTransport")(function* () {
|
|
|
124
130
|
});
|
|
125
131
|
|
|
126
132
|
const issueWebSocketTicket = Effect.fn("AuthTransport.issueWebSocketTicket")(function* (
|
|
127
|
-
|
|
133
|
+
connection: AuthTransportConnection,
|
|
128
134
|
) {
|
|
129
|
-
const url = yield* makeHttpEndpointUrl(
|
|
130
|
-
const request = HttpClientRequest.post(url).pipe(authenticatedRequest(
|
|
135
|
+
const url = yield* makeHttpEndpointUrl(connection.url, "/api/auth/websocket-ticket");
|
|
136
|
+
const request = HttpClientRequest.post(url).pipe(authenticatedRequest(connection));
|
|
131
137
|
const response = yield* client.execute(request).pipe(
|
|
132
138
|
Effect.catchTags({
|
|
133
139
|
HttpClientError: (error) =>
|
|
@@ -167,8 +173,8 @@ const makeT3AuthTransport = Effect.fn("makeT3AuthTransport")(function* () {
|
|
|
167
173
|
export const T3AuthTransportLive = Layer.effect(T3AuthTransport, makeT3AuthTransport());
|
|
168
174
|
|
|
169
175
|
const authenticatedRequest =
|
|
170
|
-
(
|
|
171
|
-
request.pipe(HttpClientRequest.acceptJson, HttpClientRequest.bearerToken(
|
|
176
|
+
(connection: AuthTransportConnection) => (request: HttpClientRequest.HttpClientRequest) =>
|
|
177
|
+
request.pipe(HttpClientRequest.acceptJson, HttpClientRequest.bearerToken(connection.token));
|
|
172
178
|
|
|
173
179
|
function makeHttpEndpointUrl(baseUrl: string, path: string) {
|
|
174
180
|
return toHttpEndpointUrl(baseUrl, path).pipe(
|
package/src/auth/type.ts
CHANGED
|
@@ -7,8 +7,14 @@ export type PairingUrl = {
|
|
|
7
7
|
readonly credential: string;
|
|
8
8
|
};
|
|
9
9
|
|
|
10
|
+
export type AuthConfigInput = {
|
|
11
|
+
readonly url: string;
|
|
12
|
+
readonly token: string;
|
|
13
|
+
};
|
|
14
|
+
|
|
10
15
|
export type PairResult = {
|
|
11
16
|
readonly url: string;
|
|
17
|
+
readonly token: string;
|
|
12
18
|
readonly role: AuthBearerBootstrapResult["role"];
|
|
13
19
|
readonly expiresAt: string;
|
|
14
20
|
};
|
|
@@ -21,8 +27,24 @@ export type LocalAuthInput = {
|
|
|
21
27
|
readonly subject: string;
|
|
22
28
|
};
|
|
23
29
|
|
|
30
|
+
export type LocalAuthTokenInput = Omit<LocalAuthInput, "origin">;
|
|
31
|
+
|
|
32
|
+
export type LocalAuthOriginInput = {
|
|
33
|
+
readonly baseDir?: string;
|
|
34
|
+
readonly origin?: string;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export type LocalAuthTokenResult = {
|
|
38
|
+
readonly token: string;
|
|
39
|
+
readonly role: AuthSessionRole;
|
|
40
|
+
readonly expiresAt: string;
|
|
41
|
+
readonly source: "local";
|
|
42
|
+
readonly baseDir: string;
|
|
43
|
+
};
|
|
44
|
+
|
|
24
45
|
export type LocalAuthResult = {
|
|
25
46
|
readonly url: string;
|
|
47
|
+
readonly token: string;
|
|
26
48
|
readonly role: AuthSessionRole;
|
|
27
49
|
readonly expiresAt: string;
|
|
28
50
|
readonly source: "local";
|
package/src/cli/auth.ts
CHANGED
|
@@ -35,6 +35,7 @@ const pairCommand = Command.make(
|
|
|
35
35
|
const output = yield* T3Output;
|
|
36
36
|
const resolvedFormat = resolveOutputFormat(format, environment, "json");
|
|
37
37
|
const result = yield* auth.pair(url);
|
|
38
|
+
yield* auth.writeConfig(result);
|
|
38
39
|
if (resolvedFormat === "json") {
|
|
39
40
|
yield* output.printJson(result);
|
|
40
41
|
} else {
|
|
@@ -66,6 +67,7 @@ const localCommand = Command.make(
|
|
|
66
67
|
...(Option.isSome(baseDir) ? { baseDir: baseDir.value } : {}),
|
|
67
68
|
...(Option.isSome(origin) ? { origin: origin.value } : {}),
|
|
68
69
|
});
|
|
70
|
+
yield* auth.writeConfig(result);
|
|
69
71
|
if (resolvedFormat === "json") {
|
|
70
72
|
yield* output.printJson(formatAuthLocalJson(result));
|
|
71
73
|
} else {
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import * as Layer from "effect/Layer";
|
|
2
|
+
|
|
3
|
+
import { T3AuthTransportLive } from "../auth/transport.ts";
|
|
4
|
+
import { T3RpcLive } from "../rpc/layer.ts";
|
|
5
|
+
|
|
6
|
+
export function makeT3CodeRpcLayer() {
|
|
7
|
+
return T3RpcLive.pipe(Layer.provide(T3AuthTransportLive));
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export const T3CodeRpcLayer = makeT3CodeRpcLayer();
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import * as Layer from "effect/Layer";
|
|
2
|
+
import * as NodeHttpClient from "@effect/platform-node/NodeHttpClient";
|
|
3
|
+
import * as NodeSocket from "@effect/platform-node/NodeSocket";
|
|
4
|
+
|
|
5
|
+
import { T3CodeRpcLayer } from "./layer.ts";
|
|
6
|
+
|
|
7
|
+
const NodeConnectionPlatformLayer = Layer.mergeAll(
|
|
8
|
+
NodeHttpClient.layerUndici,
|
|
9
|
+
NodeSocket.layerWebSocketConstructor,
|
|
10
|
+
);
|
|
11
|
+
|
|
12
|
+
export const T3CodeNodeRpcLayer = T3CodeRpcLayer.pipe(Layer.provide(NodeConnectionPlatformLayer));
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import * as Context from "effect/Context";
|
|
2
|
+
import * as Effect from "effect/Effect";
|
|
3
|
+
import * as Layer from "effect/Layer";
|
|
4
|
+
|
|
5
|
+
import type { T3CodeConnectionError } from "./error.ts";
|
|
6
|
+
import type { T3CodeConnection } from "./type.ts";
|
|
7
|
+
|
|
8
|
+
export class T3CodeConnectionProvider extends Context.Service<
|
|
9
|
+
T3CodeConnectionProvider,
|
|
10
|
+
{
|
|
11
|
+
readonly get: Effect.Effect<T3CodeConnection, T3CodeConnectionError>;
|
|
12
|
+
}
|
|
13
|
+
>()("t3cli/T3CodeConnectionProvider") {}
|
|
14
|
+
|
|
15
|
+
export function makeT3CodeConnectionProvider(
|
|
16
|
+
get: Effect.Effect<T3CodeConnection, T3CodeConnectionError>,
|
|
17
|
+
): T3CodeConnectionProvider["Service"] {
|
|
18
|
+
return { get };
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function T3CodeConnectionProviderLive(connection: T3CodeConnection) {
|
|
22
|
+
return Layer.succeed(
|
|
23
|
+
T3CodeConnectionProvider,
|
|
24
|
+
makeT3CodeConnectionProvider(Effect.succeed(connection)),
|
|
25
|
+
);
|
|
26
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export { T3CodeConnectionError } from "./connection/error.ts";
|
|
2
|
+
export { T3CodeRpcLayer, makeT3CodeRpcLayer } from "./connection/layer.ts";
|
|
3
|
+
export { T3CodeNodeRpcLayer } from "./connection/node.ts";
|
|
4
|
+
export {
|
|
5
|
+
T3CodeConnectionProvider,
|
|
6
|
+
T3CodeConnectionProviderLive,
|
|
7
|
+
makeT3CodeConnectionProvider,
|
|
8
|
+
} from "./connection/service.ts";
|
|
9
|
+
export type { T3CodeAuth, T3CodeConnection, T3CodeOrigin } from "./connection/type.ts";
|
package/src/index.ts
CHANGED
|
@@ -6,8 +6,82 @@ export type {
|
|
|
6
6
|
WaitEvent,
|
|
7
7
|
} from "./application/service.ts";
|
|
8
8
|
export type { ApplicationError } from "./application/error.ts";
|
|
9
|
+
export { T3Auth } from "./auth/service.ts";
|
|
10
|
+
export { T3AuthLive, makeT3Auth } from "./auth/layer.ts";
|
|
11
|
+
export { T3LocalAuth, T3LocalAuthLive, makeT3LocalAuth } from "./auth/local.ts";
|
|
12
|
+
export {
|
|
13
|
+
T3LocalAuthOrigin,
|
|
14
|
+
T3LocalAuthOriginLive,
|
|
15
|
+
makeT3LocalAuthOrigin,
|
|
16
|
+
} from "./auth/local-origin.ts";
|
|
17
|
+
export {
|
|
18
|
+
T3LocalAuthToken,
|
|
19
|
+
T3LocalAuthTokenLive,
|
|
20
|
+
makeT3LocalAuthToken,
|
|
21
|
+
} from "./auth/local-token.ts";
|
|
22
|
+
export {
|
|
23
|
+
T3AuthPairing,
|
|
24
|
+
T3AuthPairingLive,
|
|
25
|
+
makeT3AuthPairing,
|
|
26
|
+
parsePairingUrl,
|
|
27
|
+
} from "./auth/pairing.ts";
|
|
28
|
+
export {
|
|
29
|
+
AuthConfigError,
|
|
30
|
+
AuthLocalDatabaseError,
|
|
31
|
+
AuthLocalError,
|
|
32
|
+
AuthLocalSecretError,
|
|
33
|
+
AuthLocalSigningError,
|
|
34
|
+
AuthPairingUrlError,
|
|
35
|
+
AuthTransportError,
|
|
36
|
+
} from "./auth/error.ts";
|
|
37
|
+
export type { AuthError } from "./auth/error.ts";
|
|
38
|
+
export type { AuthSessionState, AuthWebSocketTicketResult } from "./auth/schema.ts";
|
|
39
|
+
export type {
|
|
40
|
+
AuthConfigInput,
|
|
41
|
+
AuthSessionRole,
|
|
42
|
+
LocalAuthInput,
|
|
43
|
+
LocalAuthOriginInput,
|
|
44
|
+
LocalAuthResult,
|
|
45
|
+
LocalAuthTokenInput,
|
|
46
|
+
LocalAuthTokenResult,
|
|
47
|
+
PairingUrl,
|
|
48
|
+
PairResult,
|
|
49
|
+
} from "./auth/type.ts";
|
|
50
|
+
export { T3Config } from "./config/service.ts";
|
|
51
|
+
export type { ResolvedConfig, StoredConfig } from "./config/service.ts";
|
|
52
|
+
export { T3ConfigLive, makeT3Config } from "./config/layer.ts";
|
|
53
|
+
export { ConfigError, UrlError } from "./config/error.ts";
|
|
54
|
+
export type { ConfigServiceError } from "./config/error.ts";
|
|
55
|
+
export {
|
|
56
|
+
makeT3CodeConnectionProvider,
|
|
57
|
+
makeT3CodeRpcLayer,
|
|
58
|
+
T3CodeConnectionProvider,
|
|
59
|
+
T3CodeConnectionProviderLive,
|
|
60
|
+
T3CodeNodeRpcLayer,
|
|
61
|
+
T3CodeRpcLayer,
|
|
62
|
+
T3CodeConnectionError,
|
|
63
|
+
} from "./connection.ts";
|
|
64
|
+
export type { T3CodeAuth, T3CodeConnection, T3CodeOrigin } from "./connection.ts";
|
|
65
|
+
export { Environment } from "./environment/service.ts";
|
|
66
|
+
export type { EnvironmentShape } from "./environment/service.ts";
|
|
9
67
|
export { NodeEnvironmentLive } from "./environment/layer.ts";
|
|
10
|
-
export {
|
|
68
|
+
export {
|
|
69
|
+
AppLayer,
|
|
70
|
+
AuthAppLayer,
|
|
71
|
+
T3AuthLayer,
|
|
72
|
+
T3AuthPairingLayer,
|
|
73
|
+
T3AuthTransportLayer,
|
|
74
|
+
T3LocalAuthLayer,
|
|
75
|
+
T3LocalAuthOriginLayer,
|
|
76
|
+
T3LocalAuthTokenLayer,
|
|
77
|
+
} from "./runtime.ts";
|
|
78
|
+
export { SqlClientFactory } from "./sql/service.ts";
|
|
79
|
+
export type { SqlClientFactoryShape, SqliteClientConfig } from "./sql/service.ts";
|
|
80
|
+
export {
|
|
81
|
+
NodeSqlClientFactoryLive,
|
|
82
|
+
NodeSqliteClientLive,
|
|
83
|
+
makeNodeSqliteClient,
|
|
84
|
+
} from "./sql/node-sqlite-client.ts";
|
|
11
85
|
export type {
|
|
12
86
|
OrchestrationMessage,
|
|
13
87
|
OrchestrationProjectShell,
|
package/src/rpc/error.ts
CHANGED
|
@@ -9,13 +9,9 @@ import {
|
|
|
9
9
|
import { HttpClientError } from "effect/unstable/http";
|
|
10
10
|
import { RpcClientError } from "effect/unstable/rpc";
|
|
11
11
|
|
|
12
|
-
import {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
AuthPairingUrlError,
|
|
16
|
-
AuthTransportError,
|
|
17
|
-
} from "../auth/error.ts";
|
|
18
|
-
import { ConfigError, UrlError } from "../config/error.ts";
|
|
12
|
+
import { AuthTransportError } from "../auth/error.ts";
|
|
13
|
+
import { T3CodeConnectionError } from "../connection/error.ts";
|
|
14
|
+
import { UrlError } from "../config/error.ts";
|
|
19
15
|
|
|
20
16
|
const RpcErrorCauseSchema = Schema.Union([
|
|
21
17
|
RpcClientError.RpcClientError,
|
|
@@ -24,11 +20,8 @@ const RpcErrorCauseSchema = Schema.Union([
|
|
|
24
20
|
OrchestrationDispatchCommandError,
|
|
25
21
|
OrchestrationGetSnapshotError,
|
|
26
22
|
ServerSettingsError,
|
|
27
|
-
AuthConfigError,
|
|
28
|
-
AuthLocalError,
|
|
29
|
-
AuthPairingUrlError,
|
|
30
23
|
AuthTransportError,
|
|
31
|
-
|
|
24
|
+
T3CodeConnectionError,
|
|
32
25
|
HttpClientError.HttpClientErrorSchema,
|
|
33
26
|
UrlError,
|
|
34
27
|
Schema.instanceOf(Schema.SchemaError),
|
package/src/rpc/layer.ts
CHANGED
|
@@ -6,14 +6,13 @@ import * as Option from "effect/Option";
|
|
|
6
6
|
import * as Schedule from "effect/Schedule";
|
|
7
7
|
import * as Scope from "effect/Scope";
|
|
8
8
|
import * as SynchronizedRef from "effect/SynchronizedRef";
|
|
9
|
-
import * as NodeSocket from "@effect/platform-node/NodeSocket";
|
|
10
9
|
import { HttpClientRequest } from "effect/unstable/http";
|
|
11
10
|
import { RpcClient, RpcSerialization } from "effect/unstable/rpc";
|
|
12
11
|
import * as Socket from "effect/unstable/socket/Socket";
|
|
13
12
|
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import { toWebSocketEndpointUrl } from "../config/url.ts";
|
|
13
|
+
import { T3AuthTransport } from "../auth/transport.ts";
|
|
14
|
+
import { T3CodeConnectionProvider } from "../connection/service.ts";
|
|
15
|
+
import { normalizeHttpBaseUrl, toWebSocketEndpointUrl } from "../config/url.ts";
|
|
17
16
|
import { CliWsRpcGroup } from "./ws-group.ts";
|
|
18
17
|
import { RpcError } from "./error.ts";
|
|
19
18
|
import { T3Rpc, type WsClient } from "./service.ts";
|
|
@@ -27,15 +26,19 @@ type Connection = {
|
|
|
27
26
|
};
|
|
28
27
|
|
|
29
28
|
export const makeT3RpcLayer = Effect.fn("makeT3RpcLayer")(function* () {
|
|
30
|
-
const
|
|
31
|
-
const
|
|
29
|
+
const connectionProvider = yield* T3CodeConnectionProvider;
|
|
30
|
+
const authTransport = yield* T3AuthTransport;
|
|
31
|
+
const webSocketConstructor = yield* Socket.WebSocketConstructor;
|
|
32
32
|
const parentScope = yield* Scope.Scope;
|
|
33
33
|
const connection = yield* SynchronizedRef.make(Option.none<Connection>());
|
|
34
34
|
const openConnection = Effect.fn("T3RpcLive.openConnection")(function* () {
|
|
35
35
|
const scope = yield* Scope.fork(parentScope);
|
|
36
36
|
return yield* Effect.gen(function* () {
|
|
37
|
-
const url = yield* makeWsUrl({
|
|
38
|
-
const protocol = yield* Layer.buildWithScope(
|
|
37
|
+
const url = yield* makeWsUrl({ authTransport, connectionProvider });
|
|
38
|
+
const protocol = yield* Layer.buildWithScope(
|
|
39
|
+
makeProtocolLayer(url, webSocketConstructor),
|
|
40
|
+
scope,
|
|
41
|
+
);
|
|
39
42
|
const client = yield* makeClient.pipe(
|
|
40
43
|
Effect.provide(protocol),
|
|
41
44
|
Effect.provideService(Scope.Scope, scope),
|
|
@@ -72,21 +75,28 @@ export const makeT3RpcLayer = Effect.fn("makeT3RpcLayer")(function* () {
|
|
|
72
75
|
});
|
|
73
76
|
|
|
74
77
|
const makeWsUrl = Effect.fn("makeWsUrl")(function* (input: {
|
|
75
|
-
readonly
|
|
76
|
-
readonly
|
|
78
|
+
readonly authTransport: T3AuthTransport["Service"];
|
|
79
|
+
readonly connectionProvider: T3CodeConnectionProvider["Service"];
|
|
77
80
|
}) {
|
|
78
|
-
const
|
|
79
|
-
const
|
|
80
|
-
const
|
|
81
|
+
const connection = yield* input.connectionProvider.get;
|
|
82
|
+
const origin = yield* normalizeHttpBaseUrl(connection.origin.url);
|
|
83
|
+
const wsTicket = yield* input.authTransport.issueWebSocketTicket({
|
|
84
|
+
url: origin,
|
|
85
|
+
token: connection.auth.token,
|
|
86
|
+
});
|
|
87
|
+
const wsUrl = yield* toWebSocketEndpointUrl(origin, "/ws");
|
|
81
88
|
const request = HttpClientRequest.get(wsUrl).pipe(
|
|
82
89
|
HttpClientRequest.setUrlParam("wsTicket", wsTicket.ticket),
|
|
83
90
|
);
|
|
84
91
|
return Option.getOrThrow(HttpClientRequest.toUrl(request)).toString();
|
|
85
92
|
});
|
|
86
93
|
|
|
87
|
-
function makeProtocolLayer(
|
|
94
|
+
function makeProtocolLayer(
|
|
95
|
+
url: string,
|
|
96
|
+
webSocketConstructor: Socket.WebSocketConstructor["Service"],
|
|
97
|
+
) {
|
|
88
98
|
const socketLayer = Socket.layerWebSocket(url).pipe(
|
|
89
|
-
Layer.provide(
|
|
99
|
+
Layer.provide(Layer.succeed(Socket.WebSocketConstructor, webSocketConstructor)),
|
|
90
100
|
);
|
|
91
101
|
return RpcClient.layerProtocolSocket({ retryTransientErrors: true }).pipe(
|
|
92
102
|
Layer.provide(socketLayer),
|
package/src/runtime.ts
CHANGED
|
@@ -1,31 +1,69 @@
|
|
|
1
|
+
import * as Effect from "effect/Effect";
|
|
1
2
|
import * as Layer from "effect/Layer";
|
|
2
3
|
import * as NodeHttpClient from "@effect/platform-node/NodeHttpClient";
|
|
3
4
|
import * as NodeSocket from "@effect/platform-node/NodeSocket";
|
|
4
5
|
|
|
5
6
|
import { T3AuthLive } from "./auth/layer.ts";
|
|
6
7
|
import { T3LocalAuthLive } from "./auth/local.ts";
|
|
8
|
+
import { T3LocalAuthOriginLive } from "./auth/local-origin.ts";
|
|
9
|
+
import { T3LocalAuthTokenLive } from "./auth/local-token.ts";
|
|
7
10
|
import { T3AuthPairingLive } from "./auth/pairing.ts";
|
|
8
11
|
import { T3AuthTransportLive } from "./auth/transport.ts";
|
|
12
|
+
import { T3CodeConnectionError } from "./connection/error.ts";
|
|
13
|
+
import { T3CodeConnectionProvider, makeT3CodeConnectionProvider } from "./connection/service.ts";
|
|
9
14
|
import { T3ConfigLive } from "./config/layer.ts";
|
|
15
|
+
import { T3Config } from "./config/service.ts";
|
|
10
16
|
import { T3ApplicationLive } from "./application/layer.ts";
|
|
11
17
|
import { T3OrchestrationLive } from "./orchestration/layer.ts";
|
|
12
18
|
import { T3RpcLive } from "./rpc/layer.ts";
|
|
13
19
|
import { NodeSqlClientFactoryLive } from "./sql/node-sqlite-client.ts";
|
|
14
20
|
|
|
15
|
-
const T3AuthTransportLayer = T3AuthTransportLive.pipe(
|
|
16
|
-
|
|
17
|
-
Layer.provide(Layer.mergeAll(T3ConfigLive, NodeSqlClientFactoryLive)),
|
|
21
|
+
export const T3AuthTransportLayer = T3AuthTransportLive.pipe(
|
|
22
|
+
Layer.provide(NodeHttpClient.layerUndici),
|
|
18
23
|
);
|
|
19
|
-
const
|
|
20
|
-
|
|
24
|
+
export const T3LocalAuthOriginLayer = T3LocalAuthOriginLive;
|
|
25
|
+
export const T3LocalAuthTokenLayer = T3LocalAuthTokenLive.pipe(
|
|
26
|
+
Layer.provide(NodeSqlClientFactoryLive),
|
|
21
27
|
);
|
|
22
|
-
const
|
|
28
|
+
export const T3LocalAuthLayer = T3LocalAuthLive.pipe(
|
|
29
|
+
Layer.provide(Layer.mergeAll(T3LocalAuthOriginLayer, T3LocalAuthTokenLayer)),
|
|
30
|
+
);
|
|
31
|
+
export const T3AuthPairingLayer = T3AuthPairingLive.pipe(Layer.provide(T3AuthTransportLayer));
|
|
32
|
+
export const T3AuthLayer = T3AuthLive.pipe(
|
|
23
33
|
Layer.provide(
|
|
24
34
|
Layer.mergeAll(T3ConfigLive, T3AuthTransportLayer, T3LocalAuthLayer, T3AuthPairingLayer),
|
|
25
35
|
),
|
|
26
36
|
);
|
|
37
|
+
const T3ConfigConnectionProviderLayer = Layer.effect(
|
|
38
|
+
T3CodeConnectionProvider,
|
|
39
|
+
Effect.gen(function* () {
|
|
40
|
+
const config = yield* T3Config;
|
|
41
|
+
return makeT3CodeConnectionProvider(
|
|
42
|
+
config.resolve().pipe(
|
|
43
|
+
Effect.map((resolved) => ({
|
|
44
|
+
origin: { url: resolved.url },
|
|
45
|
+
auth: { token: resolved.token },
|
|
46
|
+
})),
|
|
47
|
+
Effect.mapError(
|
|
48
|
+
(error) =>
|
|
49
|
+
new T3CodeConnectionError({
|
|
50
|
+
message: "failed to resolve T3 Code connection from CLI config",
|
|
51
|
+
cause: error,
|
|
52
|
+
}),
|
|
53
|
+
),
|
|
54
|
+
),
|
|
55
|
+
);
|
|
56
|
+
}),
|
|
57
|
+
).pipe(Layer.provide(T3ConfigLive));
|
|
58
|
+
|
|
27
59
|
const T3RpcLayer = T3RpcLive.pipe(
|
|
28
|
-
Layer.provide(
|
|
60
|
+
Layer.provide(
|
|
61
|
+
Layer.mergeAll(
|
|
62
|
+
T3ConfigConnectionProviderLayer,
|
|
63
|
+
T3AuthTransportLayer,
|
|
64
|
+
NodeSocket.layerWebSocketConstructor,
|
|
65
|
+
),
|
|
66
|
+
),
|
|
29
67
|
);
|
|
30
68
|
const T3OrchestrationLayer = T3OrchestrationLive.pipe(Layer.provide(T3RpcLayer));
|
|
31
69
|
const T3ApplicationLayer = T3ApplicationLive.pipe(Layer.provide(T3OrchestrationLayer));
|