Replace Hono with @effect/platform #2
@@ -7,9 +7,12 @@
|
||||
"start": "tsx src/index.ts"
|
||||
},
|
||||
"dependencies": {
|
||||
"@effect/platform": "^0.93.2",
|
||||
"@effect/platform-node": "^0.101.1",
|
||||
"@hono/node-server": "^1.19.5",
|
||||
"@money/shared": "workspace:*",
|
||||
"better-auth": "^1.3.27",
|
||||
"effect": "^3.19.4",
|
||||
"hono": "^4.9.12",
|
||||
"plaid": "^39.0.0",
|
||||
"tsx": "^4.20.6"
|
||||
|
||||
@@ -1,58 +1,122 @@
|
||||
import { serve } from "@hono/node-server";
|
||||
import { authDataSchema } from "@money/shared/auth";
|
||||
import { BASE_URL } from "@money/shared";
|
||||
import { cors } from "hono/cors";
|
||||
import * as Layer from "effect/Layer";
|
||||
import * as Effect from "effect/Effect";
|
||||
import * as Context from "effect/Context";
|
||||
import * as HttpLayerRouter from "@effect/platform/HttpLayerRouter";
|
||||
import * as HttpServerResponse from "@effect/platform/HttpServerResponse";
|
||||
import * as HttpServerRequest from "@effect/platform/HttpServerRequest";
|
||||
import * as NodeRuntime from "@effect/platform-node/NodeRuntime";
|
||||
import * as NodeHttpServer from "@effect/platform-node/NodeHttpServer";
|
||||
import { createServer } from "http";
|
||||
import {
|
||||
HttpApiBuilder,
|
||||
HttpApiSchema,
|
||||
HttpApiSecurity,
|
||||
} from "@effect/platform";
|
||||
import { Schema, Data, Console } from "effect";
|
||||
import { auth } from "./auth";
|
||||
import { getHono } from "./hono";
|
||||
import { zero } from "./zero";
|
||||
import { webhook } from "./webhook";
|
||||
import { AuthSchema } from "@money/shared/auth";
|
||||
|
||||
const app = getHono();
|
||||
class CurrentSession extends Context.Tag("CurrentSession")<
|
||||
CurrentSession,
|
||||
{ readonly auth: Schema.Schema.Type<typeof AuthSchema> | null }
|
||||
>() {}
|
||||
|
||||
app.use(
|
||||
"/api/*",
|
||||
cors({
|
||||
origin: ["https://money.koon.us", `${BASE_URL}:8081`],
|
||||
allowMethods: ["POST", "GET", "OPTIONS"],
|
||||
allowHeaders: ["Content-Type", "Authorization"],
|
||||
credentials: true,
|
||||
class Unauthorized extends Schema.TaggedError<Unauthorized>()(
|
||||
"Unauthorized",
|
||||
{},
|
||||
HttpApiSchema.annotations({ status: 401 }),
|
||||
) {}
|
||||
|
||||
const parseAuthorization = (input: string) =>
|
||||
Effect.gen(function* () {
|
||||
const m = /^Bearer\s+(.+)$/.exec(input);
|
||||
if (!m) {
|
||||
return yield* Effect.fail(
|
||||
new Unauthorized({ message: "Invalid Authorization header" }),
|
||||
);
|
||||
}
|
||||
return m[1];
|
||||
});
|
||||
|
||||
export class Authorization extends Context.Tag("Authorization")<
|
||||
Authorization,
|
||||
AuthorizationImpl
|
||||
>() {}
|
||||
|
||||
export interface AuthorizationImpl {
|
||||
use: <T>(
|
||||
fn: (client: typeof auth) => Promise<T>,
|
||||
) => Effect.Effect<T, AuthorizationUnknownError | AuthorizationError, never>;
|
||||
}
|
||||
|
||||
class AuthorizationUnknownError extends Data.TaggedError(
|
||||
"AuthClientUnknownError",
|
||||
) {}
|
||||
class AuthorizationError extends Data.TaggedError("AuthClientFetchError")<{
|
||||
message: string;
|
||||
}> {}
|
||||
|
||||
export const make = () =>
|
||||
Effect.gen(function* () {
|
||||
return Authorization.of({
|
||||
use: (fn) =>
|
||||
Effect.gen(function* () {
|
||||
const data = yield* Effect.tryPromise({
|
||||
try: () => fn(auth),
|
||||
catch: (error) =>
|
||||
error instanceof Error
|
||||
? new AuthorizationError({ message: error.message })
|
||||
: new AuthorizationUnknownError(),
|
||||
});
|
||||
return data;
|
||||
}),
|
||||
});
|
||||
});
|
||||
|
||||
export const AuthorizationLayer = Layer.scoped(Authorization, make());
|
||||
|
||||
const SessionMiddleware = HttpLayerRouter.middleware<{
|
||||
provides: CurrentSession;
|
||||
}>()(
|
||||
Effect.gen(function* () {
|
||||
const auth = yield* Authorization;
|
||||
|
||||
return (httpEffect) =>
|
||||
Effect.gen(function* () {
|
||||
const request = yield* HttpServerRequest.HttpServerRequest;
|
||||
const headers = request.headers;
|
||||
|
||||
const session = yield* auth
|
||||
.use((auth) => auth.api.getSession({ headers }))
|
||||
.pipe(
|
||||
Effect.flatMap((s) =>
|
||||
s == null ? Effect.succeed(null) : Schema.decode(AuthSchema)(s),
|
||||
),
|
||||
Effect.tap((s) => Console.debug("Auth result", s)),
|
||||
);
|
||||
|
||||
return yield* Effect.provideService(httpEffect, CurrentSession, {
|
||||
auth: session,
|
||||
});
|
||||
});
|
||||
}),
|
||||
);
|
||||
|
||||
app.on(["GET", "POST"], "/api/auth/*", (c) => auth.handler(c.req.raw));
|
||||
const HelloRoute = HttpLayerRouter.add(
|
||||
"GET",
|
||||
"/hello",
|
||||
|
||||
app.use("*", async (c, next) => {
|
||||
const authHeader = c.req.raw.headers.get("Authorization");
|
||||
const cookie = authHeader?.split("Bearer ")[1];
|
||||
Effect.gen(function* () {
|
||||
const { auth } = yield* CurrentSession;
|
||||
return HttpServerResponse.text(`Hello, your name is ${auth?.user.name}`);
|
||||
}),
|
||||
).pipe(Layer.provide(SessionMiddleware.layer));
|
||||
|
||||
const newHeaders = new Headers(c.req.raw.headers);
|
||||
const AllRoutes = Layer.mergeAll(HelloRoute);
|
||||
|
||||
if (cookie) {
|
||||
newHeaders.set("Cookie", cookie);
|
||||
}
|
||||
|
||||
const session = await auth.api.getSession({ headers: newHeaders });
|
||||
|
||||
if (!session) {
|
||||
c.set("auth", null);
|
||||
return next();
|
||||
}
|
||||
c.set("auth", authDataSchema.parse(session));
|
||||
return next();
|
||||
});
|
||||
|
||||
app.route("/api/zero", zero);
|
||||
|
||||
app.get("/api", (c) => c.text("OK"));
|
||||
app.get("/api/webhook_receiver", webhook);
|
||||
app.get("/", (c) => c.text("OK"));
|
||||
|
||||
serve(
|
||||
{
|
||||
fetch: app.fetch,
|
||||
port: process.env.PORT ? parseInt(process.env.PORT) : 3000,
|
||||
},
|
||||
(info) => {
|
||||
console.log(`Server is running on ${info.address}:${info.port}`);
|
||||
},
|
||||
HttpLayerRouter.serve(AllRoutes).pipe(
|
||||
Layer.provide(NodeHttpServer.layer(createServer, { port: 3000 })),
|
||||
Layer.provide(AuthorizationLayer),
|
||||
Layer.launch,
|
||||
NodeRuntime.runMain,
|
||||
);
|
||||
|
||||
58
apps/api/src/index_old.ts
Normal file
58
apps/api/src/index_old.ts
Normal file
@@ -0,0 +1,58 @@
|
||||
import { serve } from "@hono/node-server";
|
||||
import { authDataSchema } from "@money/shared/auth";
|
||||
import { BASE_URL } from "@money/shared";
|
||||
import { cors } from "hono/cors";
|
||||
import { auth } from "./auth";
|
||||
import { getHono } from "./hono";
|
||||
import { zero } from "./zero";
|
||||
import { webhook } from "./webhook";
|
||||
|
||||
const app = getHono();
|
||||
|
||||
app.use(
|
||||
"/api/*",
|
||||
cors({
|
||||
origin: ["https://money.koon.us", `${BASE_URL}:8081`],
|
||||
allowMethods: ["POST", "GET", "OPTIONS"],
|
||||
allowHeaders: ["Content-Type", "Authorization"],
|
||||
credentials: true,
|
||||
}),
|
||||
);
|
||||
|
||||
app.on(["GET", "POST"], "/api/auth/*", (c) => auth.handler(c.req.raw));
|
||||
|
||||
app.use("*", async (c, next) => {
|
||||
const authHeader = c.req.raw.headers.get("Authorization");
|
||||
const cookie = authHeader?.split("Bearer ")[1];
|
||||
|
||||
const newHeaders = new Headers(c.req.raw.headers);
|
||||
|
||||
if (cookie) {
|
||||
newHeaders.set("Cookie", cookie);
|
||||
}
|
||||
|
||||
const session = await auth.api.getSession({ headers: newHeaders });
|
||||
|
||||
if (!session) {
|
||||
c.set("auth", null);
|
||||
return next();
|
||||
}
|
||||
c.set("auth", authDataSchema.parse(session));
|
||||
return next();
|
||||
});
|
||||
|
||||
app.route("/api/zero", zero);
|
||||
|
||||
app.get("/api", (c) => c.text("OK"));
|
||||
app.get("/api/webhook_receiver", webhook);
|
||||
app.get("/", (c) => c.text("OK"));
|
||||
|
||||
serve(
|
||||
{
|
||||
fetch: app.fetch,
|
||||
port: process.env.PORT ? parseInt(process.env.PORT) : 3000,
|
||||
},
|
||||
(info) => {
|
||||
console.log(`Server is running on ${info.address}:${info.port}`);
|
||||
},
|
||||
);
|
||||
@@ -11,9 +11,9 @@ import {
|
||||
} from "effect";
|
||||
import { FileSystem } from "@effect/platform";
|
||||
import { config } from "./config";
|
||||
import { AuthState } from "./schema";
|
||||
import { authClient } from "@/lib/auth-client";
|
||||
import type { BetterFetchResponse } from "@better-fetch/fetch";
|
||||
import { AuthSchema } from "@money/shared/auth";
|
||||
|
||||
class AuthClientUnknownError extends Data.TaggedError(
|
||||
"AuthClientUnknownError",
|
||||
@@ -129,7 +129,7 @@ const pollToken = ({ device_code }: { device_code: string }) =>
|
||||
const getFromFromDisk = Effect.gen(function* () {
|
||||
const fs = yield* FileSystem.FileSystem;
|
||||
const content = yield* fs.readFileString(config.authPath);
|
||||
const auth = yield* Schema.decode(Schema.parseJson(AuthState))(content);
|
||||
const auth = yield* Schema.decode(Schema.parseJson(AuthSchema))(content);
|
||||
if (auth.session.expiresAt < new Date())
|
||||
yield* Effect.fail(new AuthClientExpiredToken());
|
||||
return auth;
|
||||
@@ -160,7 +160,7 @@ const requestAuth = Effect.gen(function* () {
|
||||
);
|
||||
if (sessionData == null) return yield* Effect.fail(new AuthClientNoData());
|
||||
|
||||
const result = yield* Schema.decodeUnknown(AuthState)(sessionData);
|
||||
const result = yield* Schema.decodeUnknown(AuthSchema)(sessionData);
|
||||
|
||||
const fs = yield* FileSystem.FileSystem;
|
||||
yield* fs.writeFileString(config.authPath, JSON.stringify(result));
|
||||
|
||||
@@ -5,13 +5,13 @@ import { ZeroProvider } from "@rocicorp/zero/react";
|
||||
import { schema } from "@money/shared";
|
||||
import { useState } from "react";
|
||||
import { AuthClientLayer, getAuth } from "./auth";
|
||||
import { Effect } from "effect";
|
||||
import { Effect, Redacted } from "effect";
|
||||
import { BunContext } from "@effect/platform-bun";
|
||||
import type { AuthData } from "./schema";
|
||||
import { kvStore } from "./store";
|
||||
import { config } from "./config";
|
||||
import { type AuthSchemaType } from "@money/shared/auth";
|
||||
|
||||
function Main({ auth }: { auth: AuthData }) {
|
||||
function Main({ auth }: { auth: AuthSchemaType }) {
|
||||
const [route, setRoute] = useState<Route>("/");
|
||||
|
||||
useKeyboard((key) => {
|
||||
@@ -22,7 +22,7 @@ function Main({ auth }: { auth: AuthData }) {
|
||||
<ZeroProvider
|
||||
{...{
|
||||
userID: auth.user.id,
|
||||
auth: auth.session.token,
|
||||
auth: Redacted.value(auth.session.token),
|
||||
server: config.zeroUrl,
|
||||
schema,
|
||||
kvStore,
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
import { Schema } from "effect";
|
||||
|
||||
const DateFromDateOrString = Schema.Union(
|
||||
Schema.DateFromString,
|
||||
Schema.DateFromSelf,
|
||||
);
|
||||
|
||||
const SessionSchema = Schema.Struct({
|
||||
expiresAt: DateFromDateOrString,
|
||||
token: Schema.String,
|
||||
createdAt: DateFromDateOrString,
|
||||
updatedAt: DateFromDateOrString,
|
||||
ipAddress: Schema.optional(Schema.NullishOr(Schema.String)),
|
||||
userAgent: Schema.optional(Schema.NullishOr(Schema.String)),
|
||||
userId: Schema.String,
|
||||
id: Schema.String,
|
||||
});
|
||||
|
||||
const UserSchema = Schema.Struct({
|
||||
name: Schema.String,
|
||||
email: Schema.String,
|
||||
emailVerified: Schema.Boolean,
|
||||
image: Schema.optional(Schema.NullishOr(Schema.String)),
|
||||
createdAt: DateFromDateOrString,
|
||||
updatedAt: DateFromDateOrString,
|
||||
id: Schema.String,
|
||||
});
|
||||
|
||||
export const AuthState = Schema.Struct({
|
||||
session: SessionSchema,
|
||||
user: UserSchema,
|
||||
});
|
||||
|
||||
export type AuthData = typeof AuthState.Type;
|
||||
@@ -1,4 +1,5 @@
|
||||
import { z } from "zod";
|
||||
import { Schema } from "effect";
|
||||
|
||||
export const sessionSchema = z.object({
|
||||
id: z.string(),
|
||||
@@ -20,6 +21,39 @@ export const authDataSchema = z.object({
|
||||
user: userSchema,
|
||||
});
|
||||
|
||||
const DateFromDateOrString = Schema.Union(
|
||||
Schema.DateFromString,
|
||||
Schema.DateFromSelf,
|
||||
);
|
||||
|
||||
export const SessionSchema = Schema.Struct({
|
||||
expiresAt: DateFromDateOrString,
|
||||
token: Schema.Redacted(Schema.String),
|
||||
createdAt: DateFromDateOrString,
|
||||
updatedAt: DateFromDateOrString,
|
||||
ipAddress: Schema.optional(Schema.NullishOr(Schema.String)),
|
||||
userAgent: Schema.optional(Schema.NullishOr(Schema.String)),
|
||||
userId: Schema.String,
|
||||
id: Schema.String,
|
||||
});
|
||||
|
||||
export const UserSchema = Schema.Struct({
|
||||
name: Schema.String,
|
||||
email: Schema.String,
|
||||
emailVerified: Schema.Boolean,
|
||||
image: Schema.optional(Schema.NullishOr(Schema.String)),
|
||||
createdAt: DateFromDateOrString,
|
||||
updatedAt: DateFromDateOrString,
|
||||
id: Schema.String,
|
||||
});
|
||||
|
||||
export const AuthSchema = Schema.Struct({
|
||||
session: SessionSchema,
|
||||
user: UserSchema,
|
||||
});
|
||||
|
||||
export type AuthSchemaType = Schema.Schema.Type<typeof AuthSchema>;
|
||||
|
||||
export type Session = z.infer<typeof sessionSchema>;
|
||||
export type User = z.infer<typeof userSchema>;
|
||||
export type AuthData = z.infer<typeof authDataSchema>;
|
||||
|
||||
62
pnpm-lock.yaml
generated
62
pnpm-lock.yaml
generated
@@ -10,6 +10,12 @@ importers:
|
||||
|
||||
apps/api:
|
||||
dependencies:
|
||||
'@effect/platform':
|
||||
specifier: ^0.93.2
|
||||
version: 0.93.2(effect@3.19.4)
|
||||
'@effect/platform-node':
|
||||
specifier: ^0.101.1
|
||||
version: 0.101.1(@effect/cluster@0.52.10(@effect/platform@0.93.2(effect@3.19.4))(@effect/rpc@0.72.1(@effect/platform@0.93.2(effect@3.19.4))(effect@3.19.4))(@effect/sql@0.48.0(@effect/experimental@0.57.1(@effect/platform@0.93.2(effect@3.19.4))(effect@3.19.4))(@effect/platform@0.93.2(effect@3.19.4))(effect@3.19.4))(@effect/workflow@0.12.5(@effect/experimental@0.57.1(@effect/platform@0.93.2(effect@3.19.4))(effect@3.19.4))(@effect/platform@0.93.2(effect@3.19.4))(@effect/rpc@0.72.1(@effect/platform@0.93.2(effect@3.19.4))(effect@3.19.4))(effect@3.19.4))(effect@3.19.4))(@effect/platform@0.93.2(effect@3.19.4))(@effect/rpc@0.72.1(@effect/platform@0.93.2(effect@3.19.4))(effect@3.19.4))(@effect/sql@0.48.0(@effect/experimental@0.57.1(@effect/platform@0.93.2(effect@3.19.4))(effect@3.19.4))(@effect/platform@0.93.2(effect@3.19.4))(effect@3.19.4))(effect@3.19.4)
|
||||
'@hono/node-server':
|
||||
specifier: ^1.19.5
|
||||
version: 1.19.6(hono@4.10.4)
|
||||
@@ -19,6 +25,9 @@ importers:
|
||||
better-auth:
|
||||
specifier: ^1.3.27
|
||||
version: 1.3.34(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||
effect:
|
||||
specifier: ^3.19.4
|
||||
version: 3.19.4
|
||||
hono:
|
||||
specifier: ^4.9.12
|
||||
version: 4.10.4
|
||||
@@ -838,6 +847,24 @@ packages:
|
||||
'@effect/sql': ^0.48.0
|
||||
effect: ^3.19.0
|
||||
|
||||
'@effect/platform-node-shared@0.54.0':
|
||||
resolution: {integrity: sha512-prTgG3CXqmrxB4Rg6utfwCTqjlGwjAEvK7R4g3HzVdFpfFRum+FQBpGHUcjyz7EejkDtBY2MWJC3Wr1QKDPjPw==}
|
||||
peerDependencies:
|
||||
'@effect/cluster': ^0.53.0
|
||||
'@effect/platform': ^0.93.3
|
||||
'@effect/rpc': ^0.72.2
|
||||
'@effect/sql': ^0.48.0
|
||||
effect: ^3.19.5
|
||||
|
||||
'@effect/platform-node@0.101.1':
|
||||
resolution: {integrity: sha512-uShujtpWU0VbdhRKhoo6tXzTG1xT0bnj8u5Q1BHpanwKPmzOhf4n0XLlMl5PaihH5Cp7xHuQlwgZlqHzhqSHzw==}
|
||||
peerDependencies:
|
||||
'@effect/cluster': ^0.53.4
|
||||
'@effect/platform': ^0.93.3
|
||||
'@effect/rpc': ^0.72.2
|
||||
'@effect/sql': ^0.48.0
|
||||
effect: ^3.19.6
|
||||
|
||||
'@effect/platform@0.93.2':
|
||||
resolution: {integrity: sha512-IFWF2xuz37tZbyEsf3hwBlcYYqbqJho+ZM871CG92lWJSjcTgvmjCy77qnV0QhTWVdh9BMs12QKzQCMlqz4cJQ==}
|
||||
peerDependencies:
|
||||
@@ -6888,6 +6915,10 @@ packages:
|
||||
resolution: {integrity: sha512-hU/10obOIu62MGYjdskASR3CUAiYaFTtC9Pa6vHyf//mAipSvSQg6od2CnJswq7fvzNS3zJhxoRkgNVaHurWKw==}
|
||||
engines: {node: '>=18.17'}
|
||||
|
||||
undici@7.16.0:
|
||||
resolution: {integrity: sha512-QEg3HPMll0o3t2ourKwOeUAZ159Kn9mx5pnzHRQO8+Wixmh88YdZRiIwat0iNzNNXn0yoEtXJqFpyW7eM8BV7g==}
|
||||
engines: {node: '>=20.18.1'}
|
||||
|
||||
unicode-canonical-property-names-ecmascript@2.0.1:
|
||||
resolution: {integrity: sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==}
|
||||
engines: {node: '>=4'}
|
||||
@@ -7936,6 +7967,35 @@ snapshots:
|
||||
- bufferutil
|
||||
- utf-8-validate
|
||||
|
||||
'@effect/platform-node-shared@0.54.0(@effect/cluster@0.52.10(@effect/platform@0.93.2(effect@3.19.4))(@effect/rpc@0.72.1(@effect/platform@0.93.2(effect@3.19.4))(effect@3.19.4))(@effect/sql@0.48.0(@effect/experimental@0.57.1(@effect/platform@0.93.2(effect@3.19.4))(effect@3.19.4))(@effect/platform@0.93.2(effect@3.19.4))(effect@3.19.4))(@effect/workflow@0.12.5(@effect/experimental@0.57.1(@effect/platform@0.93.2(effect@3.19.4))(effect@3.19.4))(@effect/platform@0.93.2(effect@3.19.4))(@effect/rpc@0.72.1(@effect/platform@0.93.2(effect@3.19.4))(effect@3.19.4))(effect@3.19.4))(effect@3.19.4))(@effect/platform@0.93.2(effect@3.19.4))(@effect/rpc@0.72.1(@effect/platform@0.93.2(effect@3.19.4))(effect@3.19.4))(@effect/sql@0.48.0(@effect/experimental@0.57.1(@effect/platform@0.93.2(effect@3.19.4))(effect@3.19.4))(@effect/platform@0.93.2(effect@3.19.4))(effect@3.19.4))(effect@3.19.4)':
|
||||
dependencies:
|
||||
'@effect/cluster': 0.52.10(@effect/platform@0.93.2(effect@3.19.4))(@effect/rpc@0.72.1(@effect/platform@0.93.2(effect@3.19.4))(effect@3.19.4))(@effect/sql@0.48.0(@effect/experimental@0.57.1(@effect/platform@0.93.2(effect@3.19.4))(effect@3.19.4))(@effect/platform@0.93.2(effect@3.19.4))(effect@3.19.4))(@effect/workflow@0.12.5(@effect/experimental@0.57.1(@effect/platform@0.93.2(effect@3.19.4))(effect@3.19.4))(@effect/platform@0.93.2(effect@3.19.4))(@effect/rpc@0.72.1(@effect/platform@0.93.2(effect@3.19.4))(effect@3.19.4))(effect@3.19.4))(effect@3.19.4)
|
||||
'@effect/platform': 0.93.2(effect@3.19.4)
|
||||
'@effect/rpc': 0.72.1(@effect/platform@0.93.2(effect@3.19.4))(effect@3.19.4)
|
||||
'@effect/sql': 0.48.0(@effect/experimental@0.57.1(@effect/platform@0.93.2(effect@3.19.4))(effect@3.19.4))(@effect/platform@0.93.2(effect@3.19.4))(effect@3.19.4)
|
||||
'@parcel/watcher': 2.5.1
|
||||
effect: 3.19.4
|
||||
multipasta: 0.2.7
|
||||
ws: 8.18.3
|
||||
transitivePeerDependencies:
|
||||
- bufferutil
|
||||
- utf-8-validate
|
||||
|
||||
'@effect/platform-node@0.101.1(@effect/cluster@0.52.10(@effect/platform@0.93.2(effect@3.19.4))(@effect/rpc@0.72.1(@effect/platform@0.93.2(effect@3.19.4))(effect@3.19.4))(@effect/sql@0.48.0(@effect/experimental@0.57.1(@effect/platform@0.93.2(effect@3.19.4))(effect@3.19.4))(@effect/platform@0.93.2(effect@3.19.4))(effect@3.19.4))(@effect/workflow@0.12.5(@effect/experimental@0.57.1(@effect/platform@0.93.2(effect@3.19.4))(effect@3.19.4))(@effect/platform@0.93.2(effect@3.19.4))(@effect/rpc@0.72.1(@effect/platform@0.93.2(effect@3.19.4))(effect@3.19.4))(effect@3.19.4))(effect@3.19.4))(@effect/platform@0.93.2(effect@3.19.4))(@effect/rpc@0.72.1(@effect/platform@0.93.2(effect@3.19.4))(effect@3.19.4))(@effect/sql@0.48.0(@effect/experimental@0.57.1(@effect/platform@0.93.2(effect@3.19.4))(effect@3.19.4))(@effect/platform@0.93.2(effect@3.19.4))(effect@3.19.4))(effect@3.19.4)':
|
||||
dependencies:
|
||||
'@effect/cluster': 0.52.10(@effect/platform@0.93.2(effect@3.19.4))(@effect/rpc@0.72.1(@effect/platform@0.93.2(effect@3.19.4))(effect@3.19.4))(@effect/sql@0.48.0(@effect/experimental@0.57.1(@effect/platform@0.93.2(effect@3.19.4))(effect@3.19.4))(@effect/platform@0.93.2(effect@3.19.4))(effect@3.19.4))(@effect/workflow@0.12.5(@effect/experimental@0.57.1(@effect/platform@0.93.2(effect@3.19.4))(effect@3.19.4))(@effect/platform@0.93.2(effect@3.19.4))(@effect/rpc@0.72.1(@effect/platform@0.93.2(effect@3.19.4))(effect@3.19.4))(effect@3.19.4))(effect@3.19.4)
|
||||
'@effect/platform': 0.93.2(effect@3.19.4)
|
||||
'@effect/platform-node-shared': 0.54.0(@effect/cluster@0.52.10(@effect/platform@0.93.2(effect@3.19.4))(@effect/rpc@0.72.1(@effect/platform@0.93.2(effect@3.19.4))(effect@3.19.4))(@effect/sql@0.48.0(@effect/experimental@0.57.1(@effect/platform@0.93.2(effect@3.19.4))(effect@3.19.4))(@effect/platform@0.93.2(effect@3.19.4))(effect@3.19.4))(@effect/workflow@0.12.5(@effect/experimental@0.57.1(@effect/platform@0.93.2(effect@3.19.4))(effect@3.19.4))(@effect/platform@0.93.2(effect@3.19.4))(@effect/rpc@0.72.1(@effect/platform@0.93.2(effect@3.19.4))(effect@3.19.4))(effect@3.19.4))(effect@3.19.4))(@effect/platform@0.93.2(effect@3.19.4))(@effect/rpc@0.72.1(@effect/platform@0.93.2(effect@3.19.4))(effect@3.19.4))(@effect/sql@0.48.0(@effect/experimental@0.57.1(@effect/platform@0.93.2(effect@3.19.4))(effect@3.19.4))(@effect/platform@0.93.2(effect@3.19.4))(effect@3.19.4))(effect@3.19.4)
|
||||
'@effect/rpc': 0.72.1(@effect/platform@0.93.2(effect@3.19.4))(effect@3.19.4)
|
||||
'@effect/sql': 0.48.0(@effect/experimental@0.57.1(@effect/platform@0.93.2(effect@3.19.4))(effect@3.19.4))(@effect/platform@0.93.2(effect@3.19.4))(effect@3.19.4)
|
||||
effect: 3.19.4
|
||||
mime: 3.0.0
|
||||
undici: 7.16.0
|
||||
ws: 8.18.3
|
||||
transitivePeerDependencies:
|
||||
- bufferutil
|
||||
- utf-8-validate
|
||||
|
||||
'@effect/platform@0.93.2(effect@3.19.4)':
|
||||
dependencies:
|
||||
effect: 3.19.4
|
||||
@@ -15764,6 +15824,8 @@ snapshots:
|
||||
|
||||
undici@6.22.0: {}
|
||||
|
||||
undici@7.16.0: {}
|
||||
|
||||
unicode-canonical-property-names-ecmascript@2.0.1: {}
|
||||
|
||||
unicode-match-property-ecmascript@2.0.0:
|
||||
|
||||
Reference in New Issue
Block a user