|
| 1 | +import { HttpApiBuilder } from "@effect/platform"; |
| 2 | +import { SyncApi } from "@local/sync"; |
| 3 | +import { LoroSchemaTransform } from "@local/sync/loro"; |
| 4 | +import { and, eq } from "drizzle-orm"; |
| 5 | +import { Array, Effect, Layer, Schema } from "effect"; |
| 6 | +import { workspaceTable } from "../db/schema"; |
| 7 | +import { Drizzle } from "../drizzle"; |
| 8 | + |
| 9 | +export const SyncDataGroupLive = HttpApiBuilder.group( |
| 10 | + SyncApi, |
| 11 | + "syncData", |
| 12 | + (handlers) => |
| 13 | + Effect.gen(function* () { |
| 14 | + const { query } = yield* Drizzle; |
| 15 | + return handlers |
| 16 | + .handle( |
| 17 | + "push", |
| 18 | + ({ payload: { clientId, snapshot }, path: { workspaceId } }) => |
| 19 | + Effect.gen(function* () { |
| 20 | + const doc = yield* Schema.encode(LoroSchemaTransform)(snapshot); |
| 21 | + |
| 22 | + const workspace = yield* query({ |
| 23 | + Request: Schema.Struct({ |
| 24 | + workspaceId: Schema.UUID, |
| 25 | + clientId: Schema.UUID, |
| 26 | + }), |
| 27 | + execute: (db, { workspaceId, clientId }) => |
| 28 | + db |
| 29 | + .select() |
| 30 | + .from(workspaceTable) |
| 31 | + .where( |
| 32 | + and( |
| 33 | + eq(workspaceTable.workspaceId, workspaceId), |
| 34 | + eq(workspaceTable.clientId, clientId) |
| 35 | + ) |
| 36 | + ) |
| 37 | + .limit(1), |
| 38 | + })({ clientId, workspaceId }).pipe(Effect.flatMap(Array.head)); |
| 39 | + |
| 40 | + doc.import(workspace.snapshot); // 🪄 |
| 41 | + |
| 42 | + const newSnapshot = |
| 43 | + yield* Schema.decode(LoroSchemaTransform)(doc); |
| 44 | + |
| 45 | + yield* query({ |
| 46 | + Request: Schema.Struct({ |
| 47 | + newSnapshot: Schema.Uint8Array, |
| 48 | + }), |
| 49 | + execute: (db, { newSnapshot: snapshot }) => |
| 50 | + db.insert(workspaceTable).values({ |
| 51 | + snapshot, |
| 52 | + clientId: workspace.clientId, |
| 53 | + workspaceId: workspace.workspaceId, |
| 54 | + ownerClientId: workspace.ownerClientId, |
| 55 | + // createdAt |
| 56 | + }), |
| 57 | + })({ newSnapshot }); |
| 58 | + |
| 59 | + return yield* Effect.fail({ |
| 60 | + message: "Not (fully) implemented" as const, |
| 61 | + }); |
| 62 | + }).pipe(Effect.mapError((error) => error.message)) |
| 63 | + ) |
| 64 | + .handle("pull", ({ path: { workspaceId } }) => |
| 65 | + Effect.fail("Not implemented") |
| 66 | + ); |
| 67 | + }) |
| 68 | +).pipe(Layer.provide(Drizzle.Default)); |
0 commit comments