Compare commits
4 Commits
ed3e6df4d2
...
effect-api
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
74f4da1d3d | ||
|
|
3ebb7ee796 | ||
|
|
02dd064d99 | ||
|
|
cbc220a968 |
@@ -9,11 +9,10 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@effect/platform": "^0.93.2",
|
"@effect/platform": "^0.93.2",
|
||||||
"@effect/platform-node": "^0.101.1",
|
"@effect/platform-node": "^0.101.1",
|
||||||
"@hono/node-server": "^1.19.5",
|
"@effect/rpc": "^0.72.2",
|
||||||
"@money/shared": "workspace:*",
|
"@money/shared": "workspace:*",
|
||||||
"better-auth": "^1.3.27",
|
"better-auth": "^1.3.27",
|
||||||
"effect": "^3.19.4",
|
"effect": "^3.19.4",
|
||||||
"hono": "^4.9.12",
|
|
||||||
"plaid": "^39.0.0",
|
"plaid": "^39.0.0",
|
||||||
"tsx": "^4.20.6"
|
"tsx": "^4.20.6"
|
||||||
},
|
},
|
||||||
|
|||||||
23
apps/api/src/auth/better-auth.ts
Normal file
23
apps/api/src/auth/better-auth.ts
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
import { Effect, Layer } from "effect";
|
||||||
|
import { Authorization } from "./context";
|
||||||
|
import { auth } from "./config";
|
||||||
|
import { AuthorizationError, AuthorizationUnknownError } from "./errors";
|
||||||
|
|
||||||
|
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 BetterAuthLive = Layer.scoped(Authorization, make());
|
||||||
@@ -3,7 +3,7 @@ import { drizzleAdapter } from "better-auth/adapters/drizzle";
|
|||||||
import { bearer, deviceAuthorization, genericOAuth } from "better-auth/plugins";
|
import { bearer, deviceAuthorization, genericOAuth } from "better-auth/plugins";
|
||||||
import { expo } from "@better-auth/expo";
|
import { expo } from "@better-auth/expo";
|
||||||
import { drizzleSchema } from "@money/shared/db";
|
import { drizzleSchema } from "@money/shared/db";
|
||||||
import { db } from "./db";
|
import { db } from "../db";
|
||||||
import { BASE_URL, HOST } from "@money/shared";
|
import { BASE_URL, HOST } from "@money/shared";
|
||||||
|
|
||||||
export const auth = betterAuth({
|
export const auth = betterAuth({
|
||||||
14
apps/api/src/auth/context.ts
Normal file
14
apps/api/src/auth/context.ts
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
import { Context, type Effect } from "effect";
|
||||||
|
import type { AuthorizationError, AuthorizationUnknownError } from "./errors";
|
||||||
|
import type { auth } from "./config";
|
||||||
|
|
||||||
|
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>;
|
||||||
|
}
|
||||||
8
apps/api/src/auth/errors.ts
Normal file
8
apps/api/src/auth/errors.ts
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
import { Data } from "effect";
|
||||||
|
|
||||||
|
export class AuthorizationUnknownError extends Data.TaggedError(
|
||||||
|
"AuthClientUnknownError",
|
||||||
|
) {}
|
||||||
|
export class AuthorizationError extends Data.TaggedError("AuthorizationError")<{
|
||||||
|
message: string;
|
||||||
|
}> {}
|
||||||
70
apps/api/src/auth/handler.ts
Normal file
70
apps/api/src/auth/handler.ts
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
import {
|
||||||
|
HttpApi,
|
||||||
|
HttpApiBuilder,
|
||||||
|
HttpApiEndpoint,
|
||||||
|
HttpApiGroup,
|
||||||
|
HttpLayerRouter,
|
||||||
|
HttpServerRequest,
|
||||||
|
} from "@effect/platform";
|
||||||
|
import * as NodeHttpServerRequest from "@effect/platform-node/NodeHttpServerRequest";
|
||||||
|
import { toNodeHandler } from "better-auth/node";
|
||||||
|
import { Effect, Layer } from "effect";
|
||||||
|
import { AuthorizationError } from "./errors";
|
||||||
|
import { auth } from "./config";
|
||||||
|
|
||||||
|
const authHandler = Effect.gen(function* () {
|
||||||
|
const request = yield* HttpServerRequest.HttpServerRequest;
|
||||||
|
const nodeRequest = NodeHttpServerRequest.toIncomingMessage(request);
|
||||||
|
const nodeResponse = NodeHttpServerRequest.toServerResponse(request);
|
||||||
|
|
||||||
|
nodeResponse.setHeader("Access-Control-Allow-Origin", "http://laptop:8081");
|
||||||
|
nodeResponse.setHeader(
|
||||||
|
"Access-Control-Allow-Methods",
|
||||||
|
"GET, POST, PUT, DELETE, OPTIONS",
|
||||||
|
);
|
||||||
|
nodeResponse.setHeader(
|
||||||
|
"Access-Control-Allow-Headers",
|
||||||
|
"Content-Type, Authorization, B3, traceparent, Cookie",
|
||||||
|
);
|
||||||
|
nodeResponse.setHeader("Access-Control-Max-Age", "600");
|
||||||
|
nodeResponse.setHeader("Access-Control-Allow-Credentials", "true");
|
||||||
|
|
||||||
|
// Handle preflight requests
|
||||||
|
if (nodeRequest.method === "OPTIONS") {
|
||||||
|
nodeResponse.statusCode = 200;
|
||||||
|
nodeResponse.end();
|
||||||
|
|
||||||
|
return;
|
||||||
|
// return nodeResponse;
|
||||||
|
}
|
||||||
|
|
||||||
|
yield* Effect.tryPromise({
|
||||||
|
try: () => toNodeHandler(auth)(nodeRequest, nodeResponse),
|
||||||
|
catch: (error) => {
|
||||||
|
return new AuthorizationError({ message: `${error}` });
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// return nodeResponse;
|
||||||
|
});
|
||||||
|
|
||||||
|
export class AuthContractGroup extends HttpApiGroup.make("auth")
|
||||||
|
.add(HttpApiEndpoint.get("get", "/*"))
|
||||||
|
.add(HttpApiEndpoint.post("post", "/*"))
|
||||||
|
.add(HttpApiEndpoint.options("options", "/*"))
|
||||||
|
.prefix("/api/auth") {}
|
||||||
|
|
||||||
|
export class DomainApi extends HttpApi.make("domain").add(AuthContractGroup) {}
|
||||||
|
|
||||||
|
export const Api = HttpApi.make("api").addHttpApi(DomainApi);
|
||||||
|
|
||||||
|
const AuthLive = HttpApiBuilder.group(Api, "auth", (handlers) =>
|
||||||
|
handlers
|
||||||
|
.handle("get", () => authHandler.pipe(Effect.orDie))
|
||||||
|
.handle("post", () => authHandler.pipe(Effect.orDie))
|
||||||
|
.handle("options", () => authHandler.pipe(Effect.orDie)),
|
||||||
|
);
|
||||||
|
|
||||||
|
export const AuthRoute = HttpLayerRouter.addHttpApi(Api).pipe(
|
||||||
|
Layer.provide(AuthLive),
|
||||||
|
);
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
import type { AuthData } from "@money/shared/auth";
|
|
||||||
import { Hono } from "hono";
|
|
||||||
|
|
||||||
export const getHono = () =>
|
|
||||||
new Hono<{ Variables: { auth: AuthData | null } }>();
|
|
||||||
@@ -1,205 +1,49 @@
|
|||||||
import * as Layer from "effect/Layer";
|
import * as Layer from "effect/Layer";
|
||||||
import * as Effect from "effect/Effect";
|
import * as Effect from "effect/Effect";
|
||||||
import * as Context from "effect/Context";
|
|
||||||
import * as HttpLayerRouter from "@effect/platform/HttpLayerRouter";
|
import * as HttpLayerRouter from "@effect/platform/HttpLayerRouter";
|
||||||
import * as HttpServerResponse from "@effect/platform/HttpServerResponse";
|
import * as HttpServerResponse from "@effect/platform/HttpServerResponse";
|
||||||
import * as HttpServerRequest from "@effect/platform/HttpServerRequest";
|
|
||||||
import * as NodeRuntime from "@effect/platform-node/NodeRuntime";
|
import * as NodeRuntime from "@effect/platform-node/NodeRuntime";
|
||||||
import * as NodeHttpServer from "@effect/platform-node/NodeHttpServer";
|
import * as NodeHttpServer from "@effect/platform-node/NodeHttpServer";
|
||||||
import * as NodeHttpServerRequest from "@effect/platform-node/NodeHttpServerRequest";
|
|
||||||
import { createServer } from "http";
|
import { createServer } from "http";
|
||||||
import {
|
import { AuthRoute } from "./auth/handler";
|
||||||
HttpApi,
|
import { BetterAuthLive } from "./auth/better-auth";
|
||||||
HttpApiBuilder,
|
import { WebhookReceiverRoute } from "./webhook";
|
||||||
HttpApiEndpoint,
|
import { ZeroMutateRoute, ZeroQueryRoute } from "./zero/handler";
|
||||||
HttpApiGroup,
|
import { RpcRoute } from "./rpc/handler";
|
||||||
HttpApiSchema,
|
|
||||||
HttpApiSecurity,
|
|
||||||
HttpMiddleware,
|
|
||||||
} from "@effect/platform";
|
|
||||||
import { Schema, Data, Console } from "effect";
|
|
||||||
import { auth } from "./auth";
|
|
||||||
import { AuthSchema } from "@money/shared/auth";
|
|
||||||
import { toNodeHandler } from "better-auth/node";
|
|
||||||
import { BASE_URL } from "@money/shared";
|
import { BASE_URL } from "@money/shared";
|
||||||
|
import { CurrentSession, SessionMiddleware } from "./middleware/session";
|
||||||
class CurrentSession extends Context.Tag("CurrentSession")<
|
|
||||||
CurrentSession,
|
|
||||||
{ readonly auth: Schema.Schema.Type<typeof AuthSchema> | null }
|
|
||||||
>() {}
|
|
||||||
|
|
||||||
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("AuthorizationError")<{
|
|
||||||
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,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
|
|
||||||
const HelloRoute = HttpLayerRouter.add(
|
|
||||||
"GET",
|
|
||||||
"/hello",
|
|
||||||
|
|
||||||
Effect.gen(function* () {
|
|
||||||
const { auth } = yield* CurrentSession;
|
|
||||||
return HttpServerResponse.text(`Hello, your name is ${auth?.user.name}`);
|
|
||||||
}),
|
|
||||||
).pipe(Layer.provide(SessionMiddleware.layer));
|
|
||||||
|
|
||||||
const RootRoute = HttpLayerRouter.add(
|
const RootRoute = HttpLayerRouter.add(
|
||||||
"GET",
|
"GET",
|
||||||
"/",
|
"/",
|
||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
|
const d = yield* CurrentSession;
|
||||||
|
|
||||||
return HttpServerResponse.text("OK");
|
return HttpServerResponse.text("OK");
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
const authHandler = Effect.gen(function* () {
|
const AllRoutes = Layer.mergeAll(
|
||||||
const request = yield* HttpServerRequest.HttpServerRequest;
|
RootRoute,
|
||||||
const nodeRequest = NodeHttpServerRequest.toIncomingMessage(request);
|
AuthRoute,
|
||||||
const nodeResponse = NodeHttpServerRequest.toServerResponse(request);
|
ZeroQueryRoute,
|
||||||
|
ZeroMutateRoute,
|
||||||
nodeResponse.setHeader("Access-Control-Allow-Origin", "http://laptop:8081");
|
RpcRoute,
|
||||||
nodeResponse.setHeader(
|
WebhookReceiverRoute,
|
||||||
"Access-Control-Allow-Methods",
|
).pipe(
|
||||||
"GET, POST, PUT, DELETE, OPTIONS",
|
Layer.provide(SessionMiddleware.layer),
|
||||||
);
|
Layer.provide(
|
||||||
nodeResponse.setHeader(
|
HttpLayerRouter.cors({
|
||||||
"Access-Control-Allow-Headers",
|
|
||||||
"Content-Type, Authorization, B3, traceparent, Cookie",
|
|
||||||
);
|
|
||||||
nodeResponse.setHeader("Access-Control-Max-Age", "600");
|
|
||||||
nodeResponse.setHeader("Access-Control-Allow-Credentials", "true");
|
|
||||||
|
|
||||||
// Handle preflight requests
|
|
||||||
if (nodeRequest.method === "OPTIONS") {
|
|
||||||
nodeResponse.statusCode = 200;
|
|
||||||
nodeResponse.end();
|
|
||||||
|
|
||||||
return;
|
|
||||||
// return nodeResponse;
|
|
||||||
}
|
|
||||||
|
|
||||||
yield* Effect.tryPromise({
|
|
||||||
try: () => toNodeHandler(auth)(nodeRequest, nodeResponse),
|
|
||||||
catch: (error) => {
|
|
||||||
return new AuthorizationError({ message: `${error}` });
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
// return nodeResponse;
|
|
||||||
});
|
|
||||||
|
|
||||||
export class AuthContractGroup extends HttpApiGroup.make("auth")
|
|
||||||
.add(HttpApiEndpoint.get("get", "/*"))
|
|
||||||
.add(HttpApiEndpoint.post("post", "/*"))
|
|
||||||
.add(HttpApiEndpoint.options("options", "/*"))
|
|
||||||
.prefix("/api/auth") {}
|
|
||||||
|
|
||||||
export class DomainApi extends HttpApi.make("domain").add(AuthContractGroup) {}
|
|
||||||
|
|
||||||
export const Api = HttpApi.make("api").addHttpApi(DomainApi);
|
|
||||||
|
|
||||||
const AuthLive = HttpApiBuilder.group(Api, "auth", (handlers) =>
|
|
||||||
handlers
|
|
||||||
.handle("get", () => authHandler.pipe(Effect.orDie))
|
|
||||||
.handle("post", () => authHandler.pipe(Effect.orDie))
|
|
||||||
.handle("options", () => authHandler.pipe(Effect.orDie)),
|
|
||||||
);
|
|
||||||
|
|
||||||
const CorsMiddleware = HttpLayerRouter.middleware(
|
|
||||||
HttpMiddleware.cors({
|
|
||||||
allowedOrigins: ["https://money.koon.us", `${BASE_URL}:8081`],
|
allowedOrigins: ["https://money.koon.us", `${BASE_URL}:8081`],
|
||||||
allowedMethods: ["POST", "GET", "OPTIONS"],
|
allowedMethods: ["POST", "GET", "OPTIONS"],
|
||||||
allowedHeaders: ["Content-Type", "Authorization"],
|
|
||||||
credentials: true,
|
credentials: true,
|
||||||
}),
|
}),
|
||||||
// {
|
),
|
||||||
// global: true,
|
|
||||||
// },
|
|
||||||
);
|
);
|
||||||
|
|
||||||
const AuthRoute = HttpLayerRouter.addHttpApi(Api).pipe(Layer.provide(AuthLive));
|
|
||||||
|
|
||||||
const AllRoutes = Layer.mergeAll(RootRoute, AuthRoute, HelloRoute);
|
|
||||||
|
|
||||||
HttpLayerRouter.serve(AllRoutes).pipe(
|
HttpLayerRouter.serve(AllRoutes).pipe(
|
||||||
Layer.provide(NodeHttpServer.layer(createServer, { port: 3000 })),
|
Layer.provide(NodeHttpServer.layer(createServer, { port: 3000 })),
|
||||||
Layer.provide(AuthorizationLayer),
|
Layer.provide(BetterAuthLive),
|
||||||
Layer.provide(CorsMiddleware.layer),
|
|
||||||
Layer.launch,
|
Layer.launch,
|
||||||
NodeRuntime.runMain,
|
NodeRuntime.runMain,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,58 +0,0 @@
|
|||||||
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}`);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
12
apps/api/src/middleware/cors.ts
Normal file
12
apps/api/src/middleware/cors.ts
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import { HttpLayerRouter, HttpMiddleware } from "@effect/platform";
|
||||||
|
import { BASE_URL } from "@money/shared";
|
||||||
|
|
||||||
|
export const CorsMiddleware = HttpLayerRouter.middleware(
|
||||||
|
HttpMiddleware.cors({
|
||||||
|
allowedOrigins: ["https://money.koon.us", `${BASE_URL}:8081`],
|
||||||
|
allowedMethods: ["POST", "GET", "OPTIONS"],
|
||||||
|
allowedHeaders: ["Content-Type", "Authorization"],
|
||||||
|
credentials: true,
|
||||||
|
}),
|
||||||
|
{ global: true },
|
||||||
|
);
|
||||||
61
apps/api/src/middleware/session.ts
Normal file
61
apps/api/src/middleware/session.ts
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
import { AuthSchema } from "@money/shared/auth";
|
||||||
|
import { Context, Effect, Schema, Console } from "effect";
|
||||||
|
import { Authorization } from "../auth/context";
|
||||||
|
import { HttpLayerRouter, HttpServerRequest } from "@effect/platform";
|
||||||
|
|
||||||
|
export class CurrentSession extends Context.Tag("CurrentSession")<
|
||||||
|
CurrentSession,
|
||||||
|
{ readonly auth: Schema.Schema.Type<typeof AuthSchema> | null }
|
||||||
|
>() {}
|
||||||
|
|
||||||
|
export 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 token = yield* HttpServerRequest.schemaHeaders(
|
||||||
|
Schema.Struct({
|
||||||
|
authorization: Schema.optional(Schema.String),
|
||||||
|
}),
|
||||||
|
).pipe(
|
||||||
|
Effect.tap(Console.debug),
|
||||||
|
Effect.flatMap(({ authorization }) =>
|
||||||
|
authorization != undefined
|
||||||
|
? parseAuthorization(authorization)
|
||||||
|
: Effect.succeed(undefined),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
if (token) {
|
||||||
|
headers["cookie"] = token;
|
||||||
|
}
|
||||||
|
|
||||||
|
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,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
const parseAuthorization = (input: string) =>
|
||||||
|
Effect.gen(function* () {
|
||||||
|
const m = /^Bearer\s+(.+)$/.exec(input);
|
||||||
|
if (!m) {
|
||||||
|
return yield* Effect.fail(new Error("Invalid token"));
|
||||||
|
}
|
||||||
|
return m[1];
|
||||||
|
});
|
||||||
76
apps/api/src/rpc/handler.ts
Normal file
76
apps/api/src/rpc/handler.ts
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
import { RpcSerialization, RpcServer } from "@effect/rpc";
|
||||||
|
import { Console, Effect, Layer, Schema } from "effect";
|
||||||
|
import { LinkRpcs, Link, AuthMiddleware } from "@money/shared/rpc";
|
||||||
|
import { CurrentSession } from "../middleware/session";
|
||||||
|
import { Authorization } from "../auth/context";
|
||||||
|
import { HttpServerRequest } from "@effect/platform";
|
||||||
|
import { AuthSchema } from "@money/shared/auth";
|
||||||
|
|
||||||
|
const parseAuthorization = (input: string) =>
|
||||||
|
Effect.gen(function* () {
|
||||||
|
const m = /^Bearer\s+(.+)$/.exec(input);
|
||||||
|
if (!m) {
|
||||||
|
return yield* Effect.fail(new Error("Invalid token"));
|
||||||
|
}
|
||||||
|
return m[1];
|
||||||
|
});
|
||||||
|
|
||||||
|
export const AuthLive = Layer.scoped(
|
||||||
|
AuthMiddleware,
|
||||||
|
Effect.gen(function* () {
|
||||||
|
const auth = yield* Authorization;
|
||||||
|
|
||||||
|
return AuthMiddleware.of(({ headers, payload, rpc }) =>
|
||||||
|
Effect.gen(function* () {
|
||||||
|
const newHeaders = { ...headers };
|
||||||
|
|
||||||
|
const token = yield* Schema.decodeUnknown(
|
||||||
|
Schema.Struct({
|
||||||
|
authorization: Schema.optional(Schema.String),
|
||||||
|
}),
|
||||||
|
)(headers).pipe(
|
||||||
|
// Effect.tap(Console.debug),
|
||||||
|
Effect.flatMap(({ authorization }) =>
|
||||||
|
authorization != undefined
|
||||||
|
? parseAuthorization(authorization)
|
||||||
|
: Effect.succeed(undefined),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (token) {
|
||||||
|
newHeaders["cookie"] = token;
|
||||||
|
}
|
||||||
|
|
||||||
|
const session = yield* auth
|
||||||
|
.use((auth) => auth.api.getSession({ headers: newHeaders }))
|
||||||
|
.pipe(
|
||||||
|
Effect.flatMap((s) =>
|
||||||
|
s == null ? Effect.succeed(null) : Schema.decode(AuthSchema)(s),
|
||||||
|
),
|
||||||
|
Effect.tap((s) => Console.debug("Auth result", s)),
|
||||||
|
);
|
||||||
|
|
||||||
|
return { auth: session };
|
||||||
|
}).pipe(Effect.orDie),
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
const LinkHandlers = LinkRpcs.toLayer({
|
||||||
|
CreateLink: () =>
|
||||||
|
Effect.gen(function* () {
|
||||||
|
const session = yield* CurrentSession;
|
||||||
|
|
||||||
|
return new Link({ href: session.auth?.user.name || "anon" });
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const RpcRoute = RpcServer.layerHttpRouter({
|
||||||
|
group: LinkRpcs,
|
||||||
|
path: "/rpc",
|
||||||
|
protocol: "http",
|
||||||
|
}).pipe(
|
||||||
|
Layer.provide(LinkHandlers),
|
||||||
|
Layer.provide(RpcSerialization.layerJson),
|
||||||
|
Layer.provide(AuthLive),
|
||||||
|
);
|
||||||
@@ -1,11 +1,21 @@
|
|||||||
import type { Context } from "hono";
|
import {
|
||||||
|
HttpLayerRouter,
|
||||||
|
HttpServerRequest,
|
||||||
|
HttpServerResponse,
|
||||||
|
} from "@effect/platform";
|
||||||
|
import { Effect } from "effect";
|
||||||
|
|
||||||
import { plaidClient } from "./plaid";
|
import { plaidClient } from "./plaid";
|
||||||
// import { LinkSessionFinishedWebhook, WebhookType } from "plaid";
|
// import { LinkSessionFinishedWebhook, WebhookType } from "plaid";
|
||||||
|
|
||||||
export const webhook = async (c: Context) => {
|
export const WebhookReceiverRoute = HttpLayerRouter.add(
|
||||||
console.log("Got webhook");
|
"*",
|
||||||
const b = await c.req.text();
|
"/api/webhook_receiver",
|
||||||
console.log("body:", b);
|
|
||||||
|
|
||||||
return c.text("Hi");
|
Effect.gen(function* () {
|
||||||
};
|
const request = yield* HttpServerRequest.HttpServerRequest;
|
||||||
|
const body = yield* request.json;
|
||||||
|
Effect.log("Got a webhook!", body);
|
||||||
|
return HttpServerResponse.text("HELLO THERE");
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|||||||
6
apps/api/src/zero/errors.ts
Normal file
6
apps/api/src/zero/errors.ts
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
import { Data } from "effect";
|
||||||
|
|
||||||
|
export class ZeroUnknownError extends Data.TaggedError("ZeroUnknownError") {}
|
||||||
|
export class ZeroError extends Data.TaggedError("ZeroError")<{
|
||||||
|
error: Error;
|
||||||
|
}> {}
|
||||||
106
apps/api/src/zero/handler.ts
Normal file
106
apps/api/src/zero/handler.ts
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
import {
|
||||||
|
HttpLayerRouter,
|
||||||
|
HttpServerRequest,
|
||||||
|
HttpServerResponse,
|
||||||
|
Url,
|
||||||
|
} from "@effect/platform";
|
||||||
|
import { Console, Effect, Layer } from "effect";
|
||||||
|
import { CurrentSession, SessionMiddleware } from "../middleware/session";
|
||||||
|
import { ZeroError, ZeroUnknownError } from "./errors";
|
||||||
|
import { withValidation, type ReadonlyJSONValue } from "@rocicorp/zero";
|
||||||
|
import {
|
||||||
|
handleGetQueriesRequest,
|
||||||
|
PushProcessor,
|
||||||
|
ZQLDatabase,
|
||||||
|
} from "@rocicorp/zero/server";
|
||||||
|
import { BASE_URL, queries, schema } from "@money/shared";
|
||||||
|
import type { AuthSchemaType } from "@money/shared/auth";
|
||||||
|
import { PostgresJSConnection } from "@rocicorp/zero/pg";
|
||||||
|
import postgres from "postgres";
|
||||||
|
import { createMutators } from "./mutators";
|
||||||
|
|
||||||
|
const processor = new PushProcessor(
|
||||||
|
new ZQLDatabase(
|
||||||
|
new PostgresJSConnection(postgres(process.env.ZERO_UPSTREAM_DB! as string)),
|
||||||
|
schema,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
export const ZeroQueryRoute = HttpLayerRouter.add(
|
||||||
|
"POST",
|
||||||
|
"/api/zero/get-queries",
|
||||||
|
|
||||||
|
Effect.gen(function* () {
|
||||||
|
const { auth } = yield* CurrentSession;
|
||||||
|
|
||||||
|
const request = yield* HttpServerRequest.HttpServerRequest;
|
||||||
|
const body = yield* request.json;
|
||||||
|
|
||||||
|
const result = yield* Effect.tryPromise({
|
||||||
|
try: () =>
|
||||||
|
handleGetQueriesRequest(
|
||||||
|
(name, args) => ({ query: getQuery(auth, name, args) }),
|
||||||
|
schema,
|
||||||
|
body as ReadonlyJSONValue,
|
||||||
|
),
|
||||||
|
catch: (error) =>
|
||||||
|
error instanceof Error
|
||||||
|
? new ZeroError({ error })
|
||||||
|
: new ZeroUnknownError(),
|
||||||
|
}).pipe(
|
||||||
|
Effect.tapErrorTag("ZeroError", (err) =>
|
||||||
|
Console.error("Zero Error", err.error),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
return yield* HttpServerResponse.json(result);
|
||||||
|
}),
|
||||||
|
).pipe(Layer.provide(SessionMiddleware.layer));
|
||||||
|
|
||||||
|
function getQuery(
|
||||||
|
authData: AuthSchemaType | null,
|
||||||
|
name: string,
|
||||||
|
args: readonly ReadonlyJSONValue[],
|
||||||
|
) {
|
||||||
|
if (name in validatedQueries) {
|
||||||
|
const q = validatedQueries[name];
|
||||||
|
return q(authData, ...args);
|
||||||
|
}
|
||||||
|
throw new Error(`Unknown query: ${name}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
export const validatedQueries = Object.fromEntries(
|
||||||
|
Object.values(queries).map((q) => [q.queryName, withValidation(q)]),
|
||||||
|
);
|
||||||
|
|
||||||
|
export const ZeroMutateRoute = HttpLayerRouter.add(
|
||||||
|
"POST",
|
||||||
|
"/api/zero/mutate",
|
||||||
|
|
||||||
|
Effect.gen(function* () {
|
||||||
|
const { auth } = yield* CurrentSession;
|
||||||
|
|
||||||
|
const request = yield* HttpServerRequest.HttpServerRequest;
|
||||||
|
const url = yield* Url.fromString(`${BASE_URL}${request.url}`);
|
||||||
|
const body = yield* request.json;
|
||||||
|
|
||||||
|
const result = yield* Effect.tryPromise({
|
||||||
|
try: () =>
|
||||||
|
processor.process(
|
||||||
|
createMutators(auth),
|
||||||
|
url.searchParams,
|
||||||
|
body as ReadonlyJSONValue,
|
||||||
|
),
|
||||||
|
catch: (error) =>
|
||||||
|
error instanceof Error
|
||||||
|
? new ZeroError({ error })
|
||||||
|
: new ZeroUnknownError(),
|
||||||
|
}).pipe(
|
||||||
|
Effect.tapErrorTag("ZeroError", (err) =>
|
||||||
|
Console.error("Zero Error", err.error),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
return yield* HttpServerResponse.json(result);
|
||||||
|
}),
|
||||||
|
).pipe(Layer.provide(SessionMiddleware.layer));
|
||||||
@@ -1,15 +1,3 @@
|
|||||||
import {
|
|
||||||
type ReadonlyJSONValue,
|
|
||||||
type Transaction,
|
|
||||||
withValidation,
|
|
||||||
} from "@rocicorp/zero";
|
|
||||||
import {
|
|
||||||
handleGetQueriesRequest,
|
|
||||||
PushProcessor,
|
|
||||||
ZQLDatabase,
|
|
||||||
} from "@rocicorp/zero/server";
|
|
||||||
import { PostgresJSConnection } from "@rocicorp/zero/pg";
|
|
||||||
import postgres from "postgres";
|
|
||||||
import {
|
import {
|
||||||
createMutators as createMutatorsShared,
|
createMutators as createMutatorsShared,
|
||||||
isLoggedIn,
|
isLoggedIn,
|
||||||
@@ -18,36 +6,27 @@ import {
|
|||||||
type Mutators,
|
type Mutators,
|
||||||
type Schema,
|
type Schema,
|
||||||
} from "@money/shared";
|
} from "@money/shared";
|
||||||
import type { AuthData } from "@money/shared/auth";
|
import type { AuthSchemaType } from "@money/shared/auth";
|
||||||
import { getHono } from "./hono";
|
|
||||||
import {
|
import {
|
||||||
Configuration,
|
type ReadonlyJSONValue,
|
||||||
CountryCode,
|
type Transaction,
|
||||||
PlaidApi,
|
withValidation,
|
||||||
PlaidEnvironments,
|
} from "@rocicorp/zero";
|
||||||
Products,
|
import { plaidClient } from "../plaid";
|
||||||
} from "plaid";
|
import { CountryCode, Products } from "plaid";
|
||||||
import { randomUUID } from "crypto";
|
|
||||||
import { db } from "./db";
|
|
||||||
import {
|
import {
|
||||||
balance,
|
balance,
|
||||||
plaidAccessTokens,
|
plaidAccessTokens,
|
||||||
plaidLink,
|
plaidLink,
|
||||||
transaction,
|
transaction,
|
||||||
} from "@money/shared/db";
|
} from "@money/shared/db";
|
||||||
|
import { db } from "../db";
|
||||||
|
import { randomUUID } from "crypto";
|
||||||
import { and, eq, inArray, sql, type InferInsertModel } from "drizzle-orm";
|
import { and, eq, inArray, sql, type InferInsertModel } from "drizzle-orm";
|
||||||
import { plaidClient } from "./plaid";
|
|
||||||
|
|
||||||
const processor = new PushProcessor(
|
|
||||||
new ZQLDatabase(
|
|
||||||
new PostgresJSConnection(postgres(process.env.ZERO_UPSTREAM_DB! as string)),
|
|
||||||
schema,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
type Tx = Transaction<Schema>;
|
type Tx = Transaction<Schema>;
|
||||||
|
|
||||||
const createMutators = (authData: AuthData | null) => {
|
export const createMutators = (authData: AuthSchemaType | null) => {
|
||||||
const mutators = createMutatorsShared(authData);
|
const mutators = createMutatorsShared(authData);
|
||||||
return {
|
return {
|
||||||
...mutators,
|
...mutators,
|
||||||
@@ -221,41 +200,3 @@ const createMutators = (authData: AuthData | null) => {
|
|||||||
},
|
},
|
||||||
} as const satisfies Mutators;
|
} as const satisfies Mutators;
|
||||||
};
|
};
|
||||||
|
|
||||||
const zero = getHono()
|
|
||||||
.post("/mutate", async (c) => {
|
|
||||||
const authData = c.get("auth");
|
|
||||||
|
|
||||||
const result = await processor.process(createMutators(authData), c.req.raw);
|
|
||||||
|
|
||||||
return c.json(result);
|
|
||||||
})
|
|
||||||
.post("/get-queries", async (c) => {
|
|
||||||
const authData = c.get("auth");
|
|
||||||
|
|
||||||
const result = await handleGetQueriesRequest(
|
|
||||||
(name, args) => ({ query: getQuery(authData, name, args) }),
|
|
||||||
schema,
|
|
||||||
c.req.raw,
|
|
||||||
);
|
|
||||||
|
|
||||||
return c.json(result);
|
|
||||||
});
|
|
||||||
|
|
||||||
const validatedQueries = Object.fromEntries(
|
|
||||||
Object.values(queries).map((q) => [q.queryName, withValidation(q)]),
|
|
||||||
);
|
|
||||||
|
|
||||||
function getQuery(
|
|
||||||
authData: AuthData | null,
|
|
||||||
name: string,
|
|
||||||
args: readonly ReadonlyJSONValue[],
|
|
||||||
) {
|
|
||||||
if (name in validatedQueries) {
|
|
||||||
const q = validatedQueries[name];
|
|
||||||
return q(authData, ...args);
|
|
||||||
}
|
|
||||||
throw new Error(`Unknown query: ${name}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
export { zero };
|
|
||||||
@@ -4,7 +4,7 @@ import "react-native-reanimated";
|
|||||||
import { authClient } from "@/lib/auth-client";
|
import { authClient } from "@/lib/auth-client";
|
||||||
import { ZeroProvider } from "@rocicorp/zero/react";
|
import { ZeroProvider } from "@rocicorp/zero/react";
|
||||||
import { useMemo } from "react";
|
import { useMemo } from "react";
|
||||||
import { authDataSchema } from "@money/shared/auth";
|
import { AuthSchema } from "@money/shared/auth";
|
||||||
import { Platform } from "react-native";
|
import { Platform } from "react-native";
|
||||||
import type { ZeroOptions } from "@rocicorp/zero";
|
import type { ZeroOptions } from "@rocicorp/zero";
|
||||||
import {
|
import {
|
||||||
@@ -15,6 +15,7 @@ import {
|
|||||||
BASE_URL,
|
BASE_URL,
|
||||||
} from "@money/shared";
|
} from "@money/shared";
|
||||||
import { expoSQLiteStoreProvider } from "@rocicorp/zero/react-native";
|
import { expoSQLiteStoreProvider } from "@rocicorp/zero/react-native";
|
||||||
|
import { Schema as S } from "effect";
|
||||||
|
|
||||||
export const unstable_settings = {
|
export const unstable_settings = {
|
||||||
anchor: "index",
|
anchor: "index",
|
||||||
@@ -26,8 +27,8 @@ export default function RootLayout() {
|
|||||||
const { data: session, isPending } = authClient.useSession();
|
const { data: session, isPending } = authClient.useSession();
|
||||||
|
|
||||||
const authData = useMemo(() => {
|
const authData = useMemo(() => {
|
||||||
const result = authDataSchema.safeParse(session);
|
const result = session ? S.decodeSync(AuthSchema)(session) : null;
|
||||||
return result.success ? result.data : null;
|
return result ? result : null;
|
||||||
}, [session]);
|
}, [session]);
|
||||||
|
|
||||||
const cookie = useMemo(() => {
|
const cookie = useMemo(() => {
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@better-auth/expo": "^1.3.27",
|
"@better-auth/expo": "^1.3.27",
|
||||||
|
"@effect-atom/atom-react": "^0.4.0",
|
||||||
"@expo/vector-icons": "^15.0.2",
|
"@expo/vector-icons": "^15.0.2",
|
||||||
"@money/shared": "workspace:*",
|
"@money/shared": "workspace:*",
|
||||||
"@money/ui": "workspace:*",
|
"@money/ui": "workspace:*",
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import { config } from "./config";
|
|||||||
import { authClient } from "@/lib/auth-client";
|
import { authClient } from "@/lib/auth-client";
|
||||||
import type { BetterFetchResponse } from "@better-fetch/fetch";
|
import type { BetterFetchResponse } from "@better-fetch/fetch";
|
||||||
import { AuthSchema } from "@money/shared/auth";
|
import { AuthSchema } from "@money/shared/auth";
|
||||||
|
import { encode } from "node:punycode";
|
||||||
|
|
||||||
class AuthClientUnknownError extends Data.TaggedError(
|
class AuthClientUnknownError extends Data.TaggedError(
|
||||||
"AuthClientUnknownError",
|
"AuthClientUnknownError",
|
||||||
@@ -161,9 +162,10 @@ const requestAuth = Effect.gen(function* () {
|
|||||||
if (sessionData == null) return yield* Effect.fail(new AuthClientNoData());
|
if (sessionData == null) return yield* Effect.fail(new AuthClientNoData());
|
||||||
|
|
||||||
const result = yield* Schema.decodeUnknown(AuthSchema)(sessionData);
|
const result = yield* Schema.decodeUnknown(AuthSchema)(sessionData);
|
||||||
|
const encoded = yield* Schema.encode(AuthSchema)(result);
|
||||||
|
|
||||||
const fs = yield* FileSystem.FileSystem;
|
const fs = yield* FileSystem.FileSystem;
|
||||||
yield* fs.writeFileString(config.authPath, JSON.stringify(result));
|
yield* fs.writeFileString(config.authPath, JSON.stringify(encoded));
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
"exports": {
|
"exports": {
|
||||||
".": "./src/index.ts",
|
".": "./src/index.ts",
|
||||||
"./auth": "./src/auth.ts",
|
"./auth": "./src/auth.ts",
|
||||||
|
"./rpc": "./src/rpc.ts",
|
||||||
"./db": "./src/db/index.ts"
|
"./db": "./src/db/index.ts"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|||||||
@@ -1,26 +1,6 @@
|
|||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { Schema } from "effect";
|
import { Schema } from "effect";
|
||||||
|
|
||||||
export const sessionSchema = z.object({
|
|
||||||
id: z.string(),
|
|
||||||
userId: z.string(),
|
|
||||||
expiresAt: z.date(),
|
|
||||||
});
|
|
||||||
|
|
||||||
export const userSchema = z.object({
|
|
||||||
id: z.string(),
|
|
||||||
email: z.string(),
|
|
||||||
emailVerified: z.boolean(),
|
|
||||||
name: z.string(),
|
|
||||||
createdAt: z.date(),
|
|
||||||
updatedAt: z.date(),
|
|
||||||
});
|
|
||||||
|
|
||||||
export const authDataSchema = z.object({
|
|
||||||
session: sessionSchema,
|
|
||||||
user: userSchema,
|
|
||||||
});
|
|
||||||
|
|
||||||
const DateFromDateOrString = Schema.Union(
|
const DateFromDateOrString = Schema.Union(
|
||||||
Schema.DateFromString,
|
Schema.DateFromString,
|
||||||
Schema.DateFromSelf,
|
Schema.DateFromSelf,
|
||||||
@@ -53,7 +33,3 @@ export const AuthSchema = Schema.Struct({
|
|||||||
});
|
});
|
||||||
|
|
||||||
export type AuthSchemaType = Schema.Schema.Type<typeof AuthSchema>;
|
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>;
|
|
||||||
|
|||||||
29
packages/shared/src/rpc.ts
Normal file
29
packages/shared/src/rpc.ts
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
import { Context, Schema } from "effect";
|
||||||
|
import { Rpc, RpcGroup, RpcMiddleware } from "@effect/rpc";
|
||||||
|
import type { AuthSchema } from "./auth";
|
||||||
|
|
||||||
|
export class Link extends Schema.Class<Link>("Link")({
|
||||||
|
href: Schema.String,
|
||||||
|
}) {}
|
||||||
|
|
||||||
|
export class CurrentSession extends Context.Tag("CurrentSession")<
|
||||||
|
CurrentSession,
|
||||||
|
{ readonly auth: Schema.Schema.Type<typeof AuthSchema> | null }
|
||||||
|
>() {}
|
||||||
|
|
||||||
|
export class AuthMiddleware extends RpcMiddleware.Tag<AuthMiddleware>()(
|
||||||
|
"AuthMiddleware",
|
||||||
|
{
|
||||||
|
// This middleware will provide the current user context
|
||||||
|
provides: CurrentSession,
|
||||||
|
// This middleware requires a client implementation too
|
||||||
|
requiredForClient: true,
|
||||||
|
},
|
||||||
|
) {}
|
||||||
|
|
||||||
|
export class LinkRpcs extends RpcGroup.make(
|
||||||
|
Rpc.make("CreateLink", {
|
||||||
|
success: Link,
|
||||||
|
error: Schema.String,
|
||||||
|
}),
|
||||||
|
).middleware(AuthMiddleware) {}
|
||||||
@@ -3,7 +3,7 @@ import { Transactions } from "./transactions";
|
|||||||
import { View, Text } from "react-native";
|
import { View, Text } from "react-native";
|
||||||
import { Settings } from "./settings";
|
import { Settings } from "./settings";
|
||||||
import { useKeyboard } from "./useKeyboard";
|
import { useKeyboard } from "./useKeyboard";
|
||||||
import type { AuthData } from "@money/shared/auth";
|
import type { AuthSchemaType } from "@money/shared/auth";
|
||||||
|
|
||||||
const PAGES = {
|
const PAGES = {
|
||||||
"/": {
|
"/": {
|
||||||
@@ -39,7 +39,7 @@ type Routes<T> = {
|
|||||||
export type Route = Routes<typeof PAGES>;
|
export type Route = Routes<typeof PAGES>;
|
||||||
|
|
||||||
interface RouterContextType {
|
interface RouterContextType {
|
||||||
auth: AuthData | null;
|
auth: AuthSchemaType | null;
|
||||||
route: Route;
|
route: Route;
|
||||||
setRoute: (route: Route) => void;
|
setRoute: (route: Route) => void;
|
||||||
}
|
}
|
||||||
@@ -51,7 +51,7 @@ export const RouterContext = createContext<RouterContextType>({
|
|||||||
});
|
});
|
||||||
|
|
||||||
type AppProps = {
|
type AppProps = {
|
||||||
auth: AuthData | null;
|
auth: AuthSchemaType | null;
|
||||||
route: Route;
|
route: Route;
|
||||||
setRoute: (page: Route) => void;
|
setRoute: (page: Route) => void;
|
||||||
};
|
};
|
||||||
|
|||||||
50
packages/ui/src/rpc.ts
Normal file
50
packages/ui/src/rpc.ts
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
import { AtomRpc } from "@effect-atom/atom-react";
|
||||||
|
import { AuthMiddleware, LinkRpcs } from "@money/shared/rpc";
|
||||||
|
import { FetchHttpClient, Headers } from "@effect/platform";
|
||||||
|
import { Rpc, RpcClient, RpcMiddleware, RpcSerialization } from "@effect/rpc";
|
||||||
|
import * as Layer from "effect/Layer";
|
||||||
|
import { Effect } from "effect";
|
||||||
|
import { use } from "react";
|
||||||
|
import { RouterContext } from "./index";
|
||||||
|
import * as Redacted from "effect/Redacted";
|
||||||
|
import { Platform } from "react-native";
|
||||||
|
|
||||||
|
const protocol = RpcClient.layerProtocolHttp({
|
||||||
|
url: "http://laptop:3000/rpc",
|
||||||
|
}).pipe(
|
||||||
|
Layer.provide([
|
||||||
|
RpcSerialization.layerJson,
|
||||||
|
FetchHttpClient.layer.pipe(
|
||||||
|
Layer.provide(
|
||||||
|
Layer.succeed(FetchHttpClient.RequestInit, {
|
||||||
|
credentials: "include",
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]),
|
||||||
|
);
|
||||||
|
|
||||||
|
export const useRpc = () => {
|
||||||
|
const { auth } = use(RouterContext);
|
||||||
|
|
||||||
|
return class Client extends AtomRpc.Tag<Client>()("RpcClient", {
|
||||||
|
group: LinkRpcs,
|
||||||
|
protocol: Layer.merge(
|
||||||
|
protocol,
|
||||||
|
RpcMiddleware.layerClient(AuthMiddleware, ({ request }) =>
|
||||||
|
Effect.succeed({
|
||||||
|
...request,
|
||||||
|
...(auth && Platform.OS == ("TUI" as any)
|
||||||
|
? {
|
||||||
|
headers: Headers.set(
|
||||||
|
request.headers,
|
||||||
|
"authorization",
|
||||||
|
"Bearer " + Redacted.value(auth.session.token),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
: {}),
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
}) {};
|
||||||
|
};
|
||||||
@@ -7,6 +7,9 @@ import { useKeyboard } from "../useKeyboard";
|
|||||||
import { Button } from "../../components/Button";
|
import { Button } from "../../components/Button";
|
||||||
import * as Table from "../../components/Table";
|
import * as Table from "../../components/Table";
|
||||||
import * as Dialog from "../../components/Dialog";
|
import * as Dialog from "../../components/Dialog";
|
||||||
|
import { useAtomSet } from "@effect-atom/atom-react";
|
||||||
|
import { useRpc } from "../rpc";
|
||||||
|
import * as Exit from "effect/Exit";
|
||||||
|
|
||||||
const COLUMNS: Table.Column[] = [
|
const COLUMNS: Table.Column[] = [
|
||||||
{ name: "name", label: "Name" },
|
{ name: "name", label: "Name" },
|
||||||
@@ -116,52 +119,79 @@ export function Accounts() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function AddAccount() {
|
function AddAccount() {
|
||||||
const { auth } = use(RouterContext);
|
const rpc = useRpc();
|
||||||
const [link, details] = useQuery(queries.getPlaidLink(auth));
|
const createLink = useAtomSet(rpc.mutation("CreateLink"), {
|
||||||
|
mode: "promiseExit",
|
||||||
|
});
|
||||||
|
|
||||||
|
const [href, setHref] = useState("");
|
||||||
|
|
||||||
|
// const [link, details] = useQuery(queries.getPlaidLink(auth));
|
||||||
const { close } = use(Dialog.Context);
|
const { close } = use(Dialog.Context);
|
||||||
|
|
||||||
const openLink = () => {
|
const init = () => {
|
||||||
if (!link) return;
|
console.log("INIT");
|
||||||
Linking.openURL(link.link);
|
const p = createLink({ payload: void 0 })
|
||||||
|
.then((link) => {
|
||||||
|
console.log("my link", link);
|
||||||
|
if (Exit.isSuccess(link)) {
|
||||||
|
setHref(link.value.href);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
console.log("WHAT");
|
||||||
|
});
|
||||||
|
console.log(p);
|
||||||
};
|
};
|
||||||
|
|
||||||
const z = useZero<Schema, Mutators>();
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
console.log(link, details);
|
console.log("useEffect");
|
||||||
if (details.type != "complete") return;
|
init();
|
||||||
if (link != undefined) {
|
}, []);
|
||||||
if (!link.completeAt) {
|
|
||||||
const timer = setInterval(() => {
|
// const openLink = () => {
|
||||||
console.log("Checking for link");
|
// if (!link) return;
|
||||||
z.mutate.link.get({ link_token: link.token });
|
// Linking.openURL(link.link);
|
||||||
}, 1000 * 5);
|
// };
|
||||||
return () => clearInterval(timer);
|
|
||||||
} else {
|
// const z = useZero<Schema, Mutators>();
|
||||||
if (close) close();
|
|
||||||
return;
|
// useEffect(() => {
|
||||||
}
|
// console.log(link, details);
|
||||||
}
|
// if (details.type != "complete") return;
|
||||||
console.log("Creating new link");
|
// if (link != undefined) {
|
||||||
z.mutate.link.create();
|
// if (!link.completeAt) {
|
||||||
}, [link, details]);
|
// const timer = setInterval(() => {
|
||||||
|
// console.log("Checking for link");
|
||||||
|
// z.mutate.link.get({ link_token: link.token });
|
||||||
|
// }, 1000 * 5);
|
||||||
|
// return () => clearInterval(timer);
|
||||||
|
// } else {
|
||||||
|
// if (close) close();
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// console.log("Creating new link");
|
||||||
|
// z.mutate.link.create();
|
||||||
|
// }, [link, details]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
<Text>Href: {href}</Text>
|
||||||
<Button onPress={() => close && close()}>close</Button>
|
<Button onPress={() => close && close()}>close</Button>
|
||||||
{link ? (
|
{/* {link ? ( */}
|
||||||
<>
|
{/* <> */}
|
||||||
<Text style={{ fontFamily: "mono" }}>
|
{/* <Text style={{ fontFamily: "mono" }}> */}
|
||||||
Please click the button to complete setup.
|
{/* Please click the button to complete setup. */}
|
||||||
</Text>
|
{/* </Text> */}
|
||||||
|
{/**/}
|
||||||
<Button shortcut="return" onPress={openLink}>
|
{/* <Button shortcut="return" onPress={openLink}> */}
|
||||||
Open Plaid
|
{/* Open Plaid */}
|
||||||
</Button>
|
{/* </Button> */}
|
||||||
</>
|
{/* </> */}
|
||||||
) : (
|
{/* ) : ( */}
|
||||||
<Text style={{ fontFamily: "mono" }}>Loading Plaid Link</Text>
|
{/* <Text style={{ fontFamily: "mono" }}>Loading Plaid Link</Text> */}
|
||||||
)}
|
{/* )} */}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
134
pnpm-lock.yaml
generated
134
pnpm-lock.yaml
generated
@@ -15,10 +15,10 @@ importers:
|
|||||||
version: 0.93.2(effect@3.19.4)
|
version: 0.93.2(effect@3.19.4)
|
||||||
'@effect/platform-node':
|
'@effect/platform-node':
|
||||||
specifier: ^0.101.1
|
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)
|
version: 0.101.1(@effect/cluster@0.52.10(@effect/platform@0.93.2(effect@3.19.4))(@effect/rpc@0.72.2(@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.2(@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.2(@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':
|
'@effect/rpc':
|
||||||
specifier: ^1.19.5
|
specifier: ^0.72.2
|
||||||
version: 1.19.6(hono@4.10.4)
|
version: 0.72.2(@effect/platform@0.93.2(effect@3.19.4))(effect@3.19.4)
|
||||||
'@money/shared':
|
'@money/shared':
|
||||||
specifier: workspace:*
|
specifier: workspace:*
|
||||||
version: link:../../packages/shared
|
version: link:../../packages/shared
|
||||||
@@ -28,9 +28,6 @@ importers:
|
|||||||
effect:
|
effect:
|
||||||
specifier: ^3.19.4
|
specifier: ^3.19.4
|
||||||
version: 3.19.4
|
version: 3.19.4
|
||||||
hono:
|
|
||||||
specifier: ^4.9.12
|
|
||||||
version: 4.10.4
|
|
||||||
plaid:
|
plaid:
|
||||||
specifier: ^39.0.0
|
specifier: ^39.0.0
|
||||||
version: 39.1.0
|
version: 39.1.0
|
||||||
@@ -47,6 +44,9 @@ importers:
|
|||||||
'@better-auth/expo':
|
'@better-auth/expo':
|
||||||
specifier: ^1.3.27
|
specifier: ^1.3.27
|
||||||
version: 1.3.34(better-auth@1.3.34(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(expo-constants@18.0.10)(expo-crypto@15.0.7(expo@54.0.23))(expo-linking@8.0.8)(expo-secure-store@15.0.7(expo@54.0.23))(expo-web-browser@15.0.9(expo@54.0.23)(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0)))
|
version: 1.3.34(better-auth@1.3.34(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(expo-constants@18.0.10)(expo-crypto@15.0.7(expo@54.0.23))(expo-linking@8.0.8)(expo-secure-store@15.0.7(expo@54.0.23))(expo-web-browser@15.0.9(expo@54.0.23)(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0)))
|
||||||
|
'@effect-atom/atom-react':
|
||||||
|
specifier: ^0.4.0
|
||||||
|
version: 0.4.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/rpc@0.72.2(@effect/platform@0.93.2(effect@3.19.4))(effect@3.19.4))(effect@3.19.4)(react@19.1.0)(scheduler@0.26.0)
|
||||||
'@expo/vector-icons':
|
'@expo/vector-icons':
|
||||||
specifier: ^15.0.2
|
specifier: ^15.0.2
|
||||||
version: 15.0.3(expo-font@14.0.9(expo@54.0.23)(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0))(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0)
|
version: 15.0.3(expo-font@14.0.9(expo@54.0.23)(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0))(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0)
|
||||||
@@ -176,7 +176,7 @@ importers:
|
|||||||
version: 0.93.2(effect@3.19.4)
|
version: 0.93.2(effect@3.19.4)
|
||||||
'@effect/platform-bun':
|
'@effect/platform-bun':
|
||||||
specifier: ^0.83.0
|
specifier: ^0.83.0
|
||||||
version: 0.83.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)
|
version: 0.83.0(@effect/cluster@0.52.10(@effect/platform@0.93.2(effect@3.19.4))(@effect/rpc@0.72.2(@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.2(@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.2(@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)
|
||||||
'@money/shared':
|
'@money/shared':
|
||||||
specifier: workspace:*
|
specifier: workspace:*
|
||||||
version: link:../../packages/shared
|
version: link:../../packages/shared
|
||||||
@@ -807,6 +807,21 @@ packages:
|
|||||||
peerDependencies:
|
peerDependencies:
|
||||||
'@noble/ciphers': ^1.0.0
|
'@noble/ciphers': ^1.0.0
|
||||||
|
|
||||||
|
'@effect-atom/atom-react@0.4.0':
|
||||||
|
resolution: {integrity: sha512-5HpKLgXEG8EWr4sBDl7BZjm6koO/5HSb94C9+OkRLDE4mhH2357vNl4uPNqid0ZNGwVvS6bAvKFmBzc0bZU6yg==}
|
||||||
|
peerDependencies:
|
||||||
|
effect: ^3.19
|
||||||
|
react: '>=18 <20'
|
||||||
|
scheduler: '*'
|
||||||
|
|
||||||
|
'@effect-atom/atom@0.4.3':
|
||||||
|
resolution: {integrity: sha512-0XOngJ+oDuJW7/Hgt09Kl8QunF1bGlEtV/K9hMB1MmQPUGb+ZtxfJwZkBeXjMPEL1Lgm04TDBlqB8+qgHz+y0w==}
|
||||||
|
peerDependencies:
|
||||||
|
'@effect/experimental': ^0.57.0
|
||||||
|
'@effect/platform': ^0.93.0
|
||||||
|
'@effect/rpc': ^0.72.1
|
||||||
|
effect: ^3.19.0
|
||||||
|
|
||||||
'@effect/cluster@0.52.10':
|
'@effect/cluster@0.52.10':
|
||||||
resolution: {integrity: sha512-csmU+4h2MXdxsFKF5eY4N52LDcjdpQp//QivOKNL9yNySUBVz/UrBr1FRgvbfHk+sxY03SNcoTNgkcbUaIp2Pg==}
|
resolution: {integrity: sha512-csmU+4h2MXdxsFKF5eY4N52LDcjdpQp//QivOKNL9yNySUBVz/UrBr1FRgvbfHk+sxY03SNcoTNgkcbUaIp2Pg==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -870,11 +885,11 @@ packages:
|
|||||||
peerDependencies:
|
peerDependencies:
|
||||||
effect: ^3.19.3
|
effect: ^3.19.3
|
||||||
|
|
||||||
'@effect/rpc@0.72.1':
|
'@effect/rpc@0.72.2':
|
||||||
resolution: {integrity: sha512-crpiAxDvFxM/fGhLuAgB1V8JOtfCm8/6ZdOP4MIdkz14I/ff3LdLJpf8hHJpYIbwYXypglAeAaHpfuZOt5f+SA==}
|
resolution: {integrity: sha512-BmTXybXCOq96D2r9mvSW/YdiTQs5CStnd4II+lfVKrMr3pMNERKLZ2LG37Tfm4Sy3Q8ire6IVVKO/CN+VR0uQQ==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
'@effect/platform': ^0.93.0
|
'@effect/platform': ^0.93.3
|
||||||
effect: ^3.19.0
|
effect: ^3.19.5
|
||||||
|
|
||||||
'@effect/sql@0.48.0':
|
'@effect/sql@0.48.0':
|
||||||
resolution: {integrity: sha512-tubdizHriDwzHUnER9UsZ/0TtF6O2WJckzeYDbVSRPeMkrpdpyEzEsoKctechTm65B3Bxy6JIixGPg2FszY72A==}
|
resolution: {integrity: sha512-tubdizHriDwzHUnER9UsZ/0TtF6O2WJckzeYDbVSRPeMkrpdpyEzEsoKctechTm65B3Bxy6JIixGPg2FszY72A==}
|
||||||
@@ -1561,12 +1576,6 @@ packages:
|
|||||||
'@hexagon/base64@1.1.28':
|
'@hexagon/base64@1.1.28':
|
||||||
resolution: {integrity: sha512-lhqDEAvWixy3bZ+UOYbPwUbBkwBq5C1LAJ/xPC8Oi+lL54oyakv/npbA0aU2hgCsx/1NUd4IBvV03+aUBWxerw==}
|
resolution: {integrity: sha512-lhqDEAvWixy3bZ+UOYbPwUbBkwBq5C1LAJ/xPC8Oi+lL54oyakv/npbA0aU2hgCsx/1NUd4IBvV03+aUBWxerw==}
|
||||||
|
|
||||||
'@hono/node-server@1.19.6':
|
|
||||||
resolution: {integrity: sha512-Shz/KjlIeAhfiuE93NDKVdZ7HdBVLQAfdbaXEaoAVO3ic9ibRSLGIQGkcBbFyuLr+7/1D5ZCINM8B+6IvXeMtw==}
|
|
||||||
engines: {node: '>=18.14.1'}
|
|
||||||
peerDependencies:
|
|
||||||
hono: ^4
|
|
||||||
|
|
||||||
'@humanfs/core@0.19.1':
|
'@humanfs/core@0.19.1':
|
||||||
resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==}
|
resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==}
|
||||||
engines: {node: '>=18.18.0'}
|
engines: {node: '>=18.18.0'}
|
||||||
@@ -4894,10 +4903,6 @@ packages:
|
|||||||
hoist-non-react-statics@3.3.2:
|
hoist-non-react-statics@3.3.2:
|
||||||
resolution: {integrity: sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==}
|
resolution: {integrity: sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==}
|
||||||
|
|
||||||
hono@4.10.4:
|
|
||||||
resolution: {integrity: sha512-YG/fo7zlU3KwrBL5vDpWKisLYiM+nVstBQqfr7gCPbSYURnNEP9BDxEMz8KfsDR9JX0lJWDRNc6nXX31v7ZEyg==}
|
|
||||||
engines: {node: '>=16.9.0'}
|
|
||||||
|
|
||||||
hosted-git-info@7.0.2:
|
hosted-git-info@7.0.2:
|
||||||
resolution: {integrity: sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==}
|
resolution: {integrity: sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==}
|
||||||
engines: {node: ^16.14.0 || >=18.0.0}
|
engines: {node: ^16.14.0 || >=18.0.0}
|
||||||
@@ -7926,12 +7931,30 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@noble/ciphers': 1.3.0
|
'@noble/ciphers': 1.3.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-atom/atom-react@0.4.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/rpc@0.72.2(@effect/platform@0.93.2(effect@3.19.4))(effect@3.19.4))(effect@3.19.4)(react@19.1.0)(scheduler@0.26.0)':
|
||||||
|
dependencies:
|
||||||
|
'@effect-atom/atom': 0.4.3(@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.2(@effect/platform@0.93.2(effect@3.19.4))(effect@3.19.4))(effect@3.19.4)
|
||||||
|
effect: 3.19.4
|
||||||
|
react: 19.1.0
|
||||||
|
scheduler: 0.26.0
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- '@effect/experimental'
|
||||||
|
- '@effect/platform'
|
||||||
|
- '@effect/rpc'
|
||||||
|
|
||||||
|
'@effect-atom/atom@0.4.3(@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.2(@effect/platform@0.93.2(effect@3.19.4))(effect@3.19.4))(effect@3.19.4)':
|
||||||
|
dependencies:
|
||||||
|
'@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.2(@effect/platform@0.93.2(effect@3.19.4))(effect@3.19.4)
|
||||||
|
effect: 3.19.4
|
||||||
|
|
||||||
|
'@effect/cluster@0.52.10(@effect/platform@0.93.2(effect@3.19.4))(@effect/rpc@0.72.2(@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.2(@effect/platform@0.93.2(effect@3.19.4))(effect@3.19.4))(effect@3.19.4))(effect@3.19.4)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@effect/platform': 0.93.2(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/rpc': 0.72.2(@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/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/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.2(@effect/platform@0.93.2(effect@3.19.4))(effect@3.19.4))(effect@3.19.4)
|
||||||
effect: 3.19.4
|
effect: 3.19.4
|
||||||
|
|
||||||
'@effect/experimental@0.57.1(@effect/platform@0.93.2(effect@3.19.4))(effect@3.19.4)':
|
'@effect/experimental@0.57.1(@effect/platform@0.93.2(effect@3.19.4))(effect@3.19.4)':
|
||||||
@@ -7940,12 +7963,12 @@ snapshots:
|
|||||||
effect: 3.19.4
|
effect: 3.19.4
|
||||||
uuid: 11.1.0
|
uuid: 11.1.0
|
||||||
|
|
||||||
'@effect/platform-bun@0.83.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/platform-bun@0.83.0(@effect/cluster@0.52.10(@effect/platform@0.93.2(effect@3.19.4))(@effect/rpc@0.72.2(@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.2(@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.2(@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:
|
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/cluster': 0.52.10(@effect/platform@0.93.2(effect@3.19.4))(@effect/rpc@0.72.2(@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.2(@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': 0.93.2(effect@3.19.4)
|
||||||
'@effect/platform-node-shared': 0.53.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/platform-node-shared': 0.53.0(@effect/cluster@0.52.10(@effect/platform@0.93.2(effect@3.19.4))(@effect/rpc@0.72.2(@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.2(@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.2(@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/rpc': 0.72.2(@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/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: 3.19.4
|
||||||
multipasta: 0.2.7
|
multipasta: 0.2.7
|
||||||
@@ -7953,11 +7976,11 @@ snapshots:
|
|||||||
- bufferutil
|
- bufferutil
|
||||||
- utf-8-validate
|
- utf-8-validate
|
||||||
|
|
||||||
'@effect/platform-node-shared@0.53.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/platform-node-shared@0.53.0(@effect/cluster@0.52.10(@effect/platform@0.93.2(effect@3.19.4))(@effect/rpc@0.72.2(@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.2(@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.2(@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:
|
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/cluster': 0.52.10(@effect/platform@0.93.2(effect@3.19.4))(@effect/rpc@0.72.2(@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.2(@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': 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/rpc': 0.72.2(@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/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
|
'@parcel/watcher': 2.5.1
|
||||||
effect: 3.19.4
|
effect: 3.19.4
|
||||||
@@ -7967,11 +7990,11 @@ snapshots:
|
|||||||
- bufferutil
|
- bufferutil
|
||||||
- utf-8-validate
|
- 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)':
|
'@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.2(@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.2(@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.2(@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:
|
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/cluster': 0.52.10(@effect/platform@0.93.2(effect@3.19.4))(@effect/rpc@0.72.2(@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.2(@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': 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/rpc': 0.72.2(@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/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
|
'@parcel/watcher': 2.5.1
|
||||||
effect: 3.19.4
|
effect: 3.19.4
|
||||||
@@ -7981,12 +8004,12 @@ snapshots:
|
|||||||
- bufferutil
|
- bufferutil
|
||||||
- utf-8-validate
|
- 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)':
|
'@effect/platform-node@0.101.1(@effect/cluster@0.52.10(@effect/platform@0.93.2(effect@3.19.4))(@effect/rpc@0.72.2(@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.2(@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.2(@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:
|
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/cluster': 0.52.10(@effect/platform@0.93.2(effect@3.19.4))(@effect/rpc@0.72.2(@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.2(@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': 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/platform-node-shared': 0.54.0(@effect/cluster@0.52.10(@effect/platform@0.93.2(effect@3.19.4))(@effect/rpc@0.72.2(@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.2(@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.2(@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/rpc': 0.72.2(@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/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: 3.19.4
|
||||||
mime: 3.0.0
|
mime: 3.0.0
|
||||||
@@ -8003,7 +8026,7 @@ snapshots:
|
|||||||
msgpackr: 1.11.5
|
msgpackr: 1.11.5
|
||||||
multipasta: 0.2.7
|
multipasta: 0.2.7
|
||||||
|
|
||||||
'@effect/rpc@0.72.1(@effect/platform@0.93.2(effect@3.19.4))(effect@3.19.4)':
|
'@effect/rpc@0.72.2(@effect/platform@0.93.2(effect@3.19.4))(effect@3.19.4)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@effect/platform': 0.93.2(effect@3.19.4)
|
'@effect/platform': 0.93.2(effect@3.19.4)
|
||||||
effect: 3.19.4
|
effect: 3.19.4
|
||||||
@@ -8016,11 +8039,11 @@ snapshots:
|
|||||||
effect: 3.19.4
|
effect: 3.19.4
|
||||||
uuid: 11.1.0
|
uuid: 11.1.0
|
||||||
|
|
||||||
'@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/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.2(@effect/platform@0.93.2(effect@3.19.4))(effect@3.19.4))(effect@3.19.4)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@effect/experimental': 0.57.1(@effect/platform@0.93.2(effect@3.19.4))(effect@3.19.4)
|
'@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/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/rpc': 0.72.2(@effect/platform@0.93.2(effect@3.19.4))(effect@3.19.4)
|
||||||
effect: 3.19.4
|
effect: 3.19.4
|
||||||
|
|
||||||
'@egjs/hammerjs@2.0.17':
|
'@egjs/hammerjs@2.0.17':
|
||||||
@@ -8474,6 +8497,7 @@ snapshots:
|
|||||||
- graphql
|
- graphql
|
||||||
- supports-color
|
- supports-color
|
||||||
- utf-8-validate
|
- utf-8-validate
|
||||||
|
optional: true
|
||||||
|
|
||||||
'@expo/code-signing-certificates@0.0.5':
|
'@expo/code-signing-certificates@0.0.5':
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -8540,6 +8564,7 @@ snapshots:
|
|||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
react: 19.2.0
|
react: 19.2.0
|
||||||
react-native: 0.82.1(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.2.0)
|
react-native: 0.82.1(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.2.0)
|
||||||
|
optional: true
|
||||||
|
|
||||||
'@expo/env@2.0.7':
|
'@expo/env@2.0.7':
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -8618,7 +8643,7 @@ snapshots:
|
|||||||
postcss: 8.4.49
|
postcss: 8.4.49
|
||||||
resolve-from: 5.0.0
|
resolve-from: 5.0.0
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
expo: 54.0.23(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.14)(react-native@0.82.1(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.2.0))(react@19.2.0)
|
expo: 54.0.23(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.14)(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0)
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- bufferutil
|
- bufferutil
|
||||||
- supports-color
|
- supports-color
|
||||||
@@ -8697,7 +8722,7 @@ snapshots:
|
|||||||
'@expo/json-file': 10.0.7
|
'@expo/json-file': 10.0.7
|
||||||
'@react-native/normalize-colors': 0.81.5
|
'@react-native/normalize-colors': 0.81.5
|
||||||
debug: 4.4.3
|
debug: 4.4.3
|
||||||
expo: 54.0.23(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.14)(react-native@0.82.1(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.2.0))(react@19.2.0)
|
expo: 54.0.23(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.14)(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0)
|
||||||
resolve-from: 5.0.0
|
resolve-from: 5.0.0
|
||||||
semver: 7.7.3
|
semver: 7.7.3
|
||||||
xml2js: 0.6.0
|
xml2js: 0.6.0
|
||||||
@@ -8725,6 +8750,7 @@ snapshots:
|
|||||||
expo-font: 14.0.9(expo@54.0.23)(react-native@0.82.1(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.2.0))(react@19.2.0)
|
expo-font: 14.0.9(expo@54.0.23)(react-native@0.82.1(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.2.0))(react@19.2.0)
|
||||||
react: 19.2.0
|
react: 19.2.0
|
||||||
react-native: 0.82.1(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.2.0)
|
react-native: 0.82.1(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.2.0)
|
||||||
|
optional: true
|
||||||
|
|
||||||
'@expo/ws-tunnel@1.0.6': {}
|
'@expo/ws-tunnel@1.0.6': {}
|
||||||
|
|
||||||
@@ -8796,10 +8822,6 @@ snapshots:
|
|||||||
|
|
||||||
'@hexagon/base64@1.1.28': {}
|
'@hexagon/base64@1.1.28': {}
|
||||||
|
|
||||||
'@hono/node-server@1.19.6(hono@4.10.4)':
|
|
||||||
dependencies:
|
|
||||||
hono: 4.10.4
|
|
||||||
|
|
||||||
'@humanfs/core@0.19.1': {}
|
'@humanfs/core@0.19.1': {}
|
||||||
|
|
||||||
'@humanfs/node@0.16.7':
|
'@humanfs/node@0.16.7':
|
||||||
@@ -10731,6 +10753,7 @@ snapshots:
|
|||||||
react-native: 0.82.1(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.2.0)
|
react-native: 0.82.1(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.2.0)
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
'@types/react': 19.1.17
|
'@types/react': 19.1.17
|
||||||
|
optional: true
|
||||||
|
|
||||||
'@react-navigation/bottom-tabs@7.8.4(@react-navigation/native@7.1.19(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0))(react-native-safe-area-context@5.6.2(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0))(react-native-screens@4.16.0(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0))(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0)':
|
'@react-navigation/bottom-tabs@7.8.4(@react-navigation/native@7.1.19(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0))(react-native-safe-area-context@5.6.2(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0))(react-native-screens@4.16.0(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0))(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0)':
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -11596,7 +11619,7 @@ snapshots:
|
|||||||
resolve-from: 5.0.0
|
resolve-from: 5.0.0
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
'@babel/runtime': 7.28.4
|
'@babel/runtime': 7.28.4
|
||||||
expo: 54.0.23(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.14)(react-native@0.82.1(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.2.0))(react@19.2.0)
|
expo: 54.0.23(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.14)(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0)
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- '@babel/core'
|
- '@babel/core'
|
||||||
- supports-color
|
- supports-color
|
||||||
@@ -12597,6 +12620,7 @@ snapshots:
|
|||||||
react-native: 0.82.1(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.2.0)
|
react-native: 0.82.1(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.2.0)
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
optional: true
|
||||||
|
|
||||||
expo-constants@18.0.10(expo@54.0.23)(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0)):
|
expo-constants@18.0.10(expo@54.0.23)(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0)):
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -12615,6 +12639,7 @@ snapshots:
|
|||||||
react-native: 0.82.1(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.2.0)
|
react-native: 0.82.1(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.2.0)
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
optional: true
|
||||||
|
|
||||||
expo-crypto@15.0.7(expo@54.0.23):
|
expo-crypto@15.0.7(expo@54.0.23):
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -12630,6 +12655,7 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
expo: 54.0.23(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.14)(react-native@0.82.1(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.2.0))(react@19.2.0)
|
expo: 54.0.23(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.14)(react-native@0.82.1(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.2.0))(react@19.2.0)
|
||||||
react-native: 0.82.1(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.2.0)
|
react-native: 0.82.1(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.2.0)
|
||||||
|
optional: true
|
||||||
|
|
||||||
expo-font@14.0.9(expo@54.0.23)(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0):
|
expo-font@14.0.9(expo@54.0.23)(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0):
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -12644,6 +12670,7 @@ snapshots:
|
|||||||
fontfaceobserver: 2.3.0
|
fontfaceobserver: 2.3.0
|
||||||
react: 19.2.0
|
react: 19.2.0
|
||||||
react-native: 0.82.1(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.2.0)
|
react-native: 0.82.1(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.2.0)
|
||||||
|
optional: true
|
||||||
|
|
||||||
expo-haptics@15.0.7(expo@54.0.23):
|
expo-haptics@15.0.7(expo@54.0.23):
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -12666,6 +12693,7 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
expo: 54.0.23(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.14)(react-native@0.82.1(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.2.0))(react@19.2.0)
|
expo: 54.0.23(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.14)(react-native@0.82.1(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.2.0))(react@19.2.0)
|
||||||
react: 19.2.0
|
react: 19.2.0
|
||||||
|
optional: true
|
||||||
|
|
||||||
expo-linking@8.0.8(expo@54.0.23)(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0):
|
expo-linking@8.0.8(expo@54.0.23)(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0):
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -12707,6 +12735,7 @@ snapshots:
|
|||||||
invariant: 2.2.4
|
invariant: 2.2.4
|
||||||
react: 19.2.0
|
react: 19.2.0
|
||||||
react-native: 0.82.1(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.2.0)
|
react-native: 0.82.1(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.2.0)
|
||||||
|
optional: true
|
||||||
|
|
||||||
expo-router@6.0.14(@expo/metro-runtime@6.1.2)(@types/react@19.1.17)(expo-constants@18.0.10)(expo-linking@8.0.8)(expo@54.0.23)(react-dom@19.1.0(react@19.1.0))(react-native-gesture-handler@2.28.0(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0))(react-native-reanimated@4.1.3(@babel/core@7.28.5)(react-native-worklets@0.5.1(@babel/core@7.28.5)(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0))(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0))(react-native-safe-area-context@5.6.2(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0))(react-native-screens@4.16.0(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0))(react-native-web@0.21.2(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0):
|
expo-router@6.0.14(@expo/metro-runtime@6.1.2)(@types/react@19.1.17)(expo-constants@18.0.10)(expo-linking@8.0.8)(expo@54.0.23)(react-dom@19.1.0(react@19.1.0))(react-native-gesture-handler@2.28.0(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0))(react-native-reanimated@4.1.3(@babel/core@7.28.5)(react-native-worklets@0.5.1(@babel/core@7.28.5)(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0))(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0))(react-native-safe-area-context@5.6.2(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0))(react-native-screens@4.16.0(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0))(react-native-web@0.21.2(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0):
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -12922,6 +12951,7 @@ snapshots:
|
|||||||
- graphql
|
- graphql
|
||||||
- supports-color
|
- supports-color
|
||||||
- utf-8-validate
|
- utf-8-validate
|
||||||
|
optional: true
|
||||||
|
|
||||||
exponential-backoff@3.1.3: {}
|
exponential-backoff@3.1.3: {}
|
||||||
|
|
||||||
@@ -13274,8 +13304,6 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
react-is: 16.13.1
|
react-is: 16.13.1
|
||||||
|
|
||||||
hono@4.10.4: {}
|
|
||||||
|
|
||||||
hosted-git-info@7.0.2:
|
hosted-git-info@7.0.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
lru-cache: 10.4.3
|
lru-cache: 10.4.3
|
||||||
@@ -15051,6 +15079,7 @@ snapshots:
|
|||||||
- bufferutil
|
- bufferutil
|
||||||
- supports-color
|
- supports-color
|
||||||
- utf-8-validate
|
- utf-8-validate
|
||||||
|
optional: true
|
||||||
|
|
||||||
react-reconciler@0.32.0(react@19.1.0):
|
react-reconciler@0.32.0(react@19.1.0):
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -15118,7 +15147,8 @@ snapshots:
|
|||||||
|
|
||||||
react@19.1.0: {}
|
react@19.1.0: {}
|
||||||
|
|
||||||
react@19.2.0: {}
|
react@19.2.0:
|
||||||
|
optional: true
|
||||||
|
|
||||||
readable-stream@3.6.2:
|
readable-stream@3.6.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
|
|||||||
Reference in New Issue
Block a user