Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
c8f7085
Add prepare script for Effect devtools
lucasdoell Apr 10, 2026
01006b9
Replace Effect.fail with direct error yield
lucasdoell Apr 10, 2026
de99fae
Refactor for consistency with new services
lucasdoell Apr 10, 2026
e2f3956
Add zed settings
lucasdoell Apr 10, 2026
5d9bc4f
Minor styling changes
lucasdoell Apr 10, 2026
4defe56
Add team shared data Effect service foundation
lucasdoell Apr 10, 2026
4d0560f
Add user, admin, hero, and tournament Effect services
lucasdoell Apr 10, 2026
8d6ebba
Add comparison Effect services
lucasdoell Apr 10, 2026
2b66a55
Add scouting and intelligence Effect services
lucasdoell Apr 10, 2026
4c71397
Add scrim Effect services
lucasdoell Apr 10, 2026
23c185e
Add player Effect services
lucasdoell Apr 10, 2026
40a1232
Add map Effect services
lucasdoell Apr 10, 2026
4661433
Add remaining team Effect services and barrel exports
lucasdoell Apr 10, 2026
f191395
Add DataLayerLive composing all service layers
lucasdoell Apr 10, 2026
c340360
Add AppRuntime singleton for native Effect consumers
lucasdoell Apr 10, 2026
4097901
Migrate user-dto consumers to native Effect
lucasdoell Apr 10, 2026
eb58ec5
Migrate scrim-dto consumers to native Effect
lucasdoell Apr 10, 2026
f9f6cdb
Migrate comparison-dto consumers to native Effect
lucasdoell Apr 10, 2026
58ba3c3
Migrate scouting-dto and opponent-strength-dto consumers to native Ef…
lucasdoell Apr 10, 2026
3347ad9
Migrate ai/tools.ts to native Effect services
lucasdoell Apr 10, 2026
8d10005
Split type exports from service exports for client component safety
lucasdoell Apr 10, 2026
fb9057c
Add team analytics and prediction Effect services
lucasdoell Apr 10, 2026
9b1d69f
Extract client-needed types from service files to types.ts
lucasdoell Apr 10, 2026
25ac1bb
Migrate client component type imports to new type paths
lucasdoell Apr 10, 2026
1f1f0f1
Migrate lib files to new Effect services and type paths
lucasdoell Apr 10, 2026
3aebd10
Migrate all remaining server pages, routes, and components to native …
lucasdoell Apr 10, 2026
9e00407
Migrate final consumer files and fix client import chain
lucasdoell Apr 10, 2026
a910f8c
Split parser into client and server modules
lucasdoell Apr 10, 2026
f26d107
Update types and remove unused imports
lucasdoell Apr 10, 2026
76d444a
Reformat
lucasdoell Apr 10, 2026
65ed49c
Delete migration-parity.test.ts
lucasdoell Apr 10, 2026
ec71873
Remove legacy DTOs
lucasdoell Apr 10, 2026
eea5b39
Update test suite to mock server-side functions
lucasdoell Apr 10, 2026
1faf0dc
Switch import to parser client
lucasdoell Apr 10, 2026
b881021
Fix linting error
lucasdoell Apr 10, 2026
7437f79
Merge pull request #72 from luxdotdev/effect-rewrite
lucasdoell Apr 10, 2026
9fcc2d4
Update cache key date string handling
lucasdoell Apr 10, 2026
0fb2d98
Update parser coordinate regex
lucasdoell Apr 10, 2026
a9e4988
Update package.json version
lucasdoell Apr 10, 2026
fe3166d
Pass mapDataId to heatmap and replay tabs
lucasdoell Apr 10, 2026
ce278bf
Fix path style for S3 client
lucasdoell Apr 10, 2026
fdbc132
Replace wrong ID for killfeed calibration data
lucasdoell Apr 10, 2026
849e534
Add fight to canvas to event timeline view
lucasdoell Apr 10, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
134 changes: 134 additions & 0 deletions .zed/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
// Folder-specific settings
//
// For a full list of overridable settings, and general information on folder-specific settings,
// see the documentation: https://zed.dev/docs/configuring-zed#settings-files
{
"lsp": {
"oxfmt": {
"initialization_options": {
"settings": {
"fmt.configPath": null
}
}
}
},
"languages": {
"CSS": {
"format_on_save": "on",
"prettier": {
"allowed": false
},
"formatter": [
{
"language_server": {
"name": "oxfmt"
}
}
]
},
"HTML": {
"format_on_save": "on",
"prettier": {
"allowed": false
},
"formatter": [
{
"language_server": {
"name": "oxfmt"
}
}
]
},
"JavaScript": {
"format_on_save": "on",
"prettier": {
"allowed": false
},
"formatter": [
{
"language_server": {
"name": "oxfmt"
}
}
]
},
"JSON": {
"format_on_save": "on",
"prettier": {
"allowed": false
},
"formatter": [
{
"language_server": {
"name": "oxfmt"
}
}
]
},
"JSONC": {
"format_on_save": "on",
"prettier": {
"allowed": false
},
"formatter": [
{
"language_server": {
"name": "oxfmt"
}
}
]
},
"Markdown": {
"format_on_save": "on",
"prettier": {
"allowed": false
},
"formatter": [
{
"language_server": {
"name": "oxfmt"
}
}
]
},
"TypeScript": {
"format_on_save": "on",
"prettier": {
"allowed": false
},
"formatter": [
{
"language_server": {
"name": "oxfmt"
}
}
]
},
"TSX": {
"format_on_save": "on",
"prettier": {
"allowed": false
},
"formatter": [
{
"language_server": {
"name": "oxfmt"
}
}
]
},
"YAML": {
"format_on_save": "on",
"prettier": {
"allowed": false
},
"formatter": [
{
"language_server": {
"name": "oxfmt"
}
}
]
}
}
}
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
{
"name": "parsertime",
"version": "2.1.0",
"version": "3.0.0",
"private": true,
"scripts": {
"dev": "next dev --turbopack",
"build": "next build",
"prepare": "effect-language-service patch",
"postinstall": "prisma generate",
"start": "next start",
"lint": "next typegen && oxlint",
Expand Down
8 changes: 6 additions & 2 deletions src/app/[team]/compare/page.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { ComparisonContent } from "@/components/compare/comparison-content";
import { DashboardLayout } from "@/components/dashboard-layout";
import { getUser } from "@/data/user-dto";
import { Effect } from "effect";
import { AppRuntime } from "@/data/runtime";
import { UserService } from "@/data/user";
import { auth } from "@/lib/auth";
import prisma from "@/lib/prisma";
import type { PagePropsWithLocale } from "@/types/next";
Expand Down Expand Up @@ -34,7 +36,9 @@ export default async function ComparePage(
notFound();
}

const user = await getUser(session.user.email);
const user = await AppRuntime.runPromise(
UserService.pipe(Effect.flatMap((svc) => svc.getUser(session.user.email)))
);
if (!user) {
notFound();
}
Expand Down
8 changes: 6 additions & 2 deletions src/app/[team]/map-groups/page.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { MapGroupManager } from "@/components/compare/map-group-manager";
import { DashboardLayout } from "@/components/dashboard-layout";
import { getUser } from "@/data/user-dto";
import { Effect } from "effect";
import { AppRuntime } from "@/data/runtime";
import { UserService } from "@/data/user";
import { auth } from "@/lib/auth";
import prisma from "@/lib/prisma";
import type { PagePropsWithLocale } from "@/types/next";
Expand Down Expand Up @@ -34,7 +36,9 @@ export default async function MapGroupsPage(
notFound();
}

const user = await getUser(session.user.email);
const user = await AppRuntime.runPromise(
UserService.pipe(Effect.flatMap((svc) => svc.getUser(session.user.email)))
);
if (!user) {
notFound();
}
Expand Down
24 changes: 18 additions & 6 deletions src/app/[team]/scrim/[scrimId]/edit/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ import { DashboardLayout } from "@/components/dashboard-layout";
import { DangerZone } from "@/components/scrim/danger-zone";
import { EditScrimForm } from "@/components/scrim/edit-scrim-form";
import { Link } from "@/components/ui/link";
import { getScoutingTeams } from "@/data/scouting-dto";
import { getScrim } from "@/data/scrim-dto";
import { getTeamsWithPerms } from "@/data/user-dto";
import { ScrimService } from "@/data/scrim";
import { Effect } from "effect";
import { AppRuntime } from "@/data/runtime";
import { ScoutingService } from "@/data/scouting";
import { UserService } from "@/data/user";
import { auth } from "@/lib/auth";
import { scoutingTool } from "@/lib/flags";
import { resolveMapDataId } from "@/lib/map-data-resolver";
Expand All @@ -16,7 +18,11 @@ export default async function EditScrimPage(
props: PageProps<"/[team]/scrim/[scrimId]/edit">
) {
const params = await props.params;
const scrim = await getScrim(parseInt(params.scrimId));
const scrim = await AppRuntime.runPromise(
ScrimService.pipe(
Effect.flatMap((svc) => svc.getScrim(parseInt(params.scrimId)))
)
);
const session = await auth();
const t = await getTranslations("scrimPage.editScrim");

Expand All @@ -26,8 +32,14 @@ export default async function EditScrimPage(

const [teamsWithPerms, scoutingTeamList, scoutingEnabled] = await Promise.all(
[
getTeamsWithPerms(session?.user?.email),
getScoutingTeams(),
AppRuntime.runPromise(
UserService.pipe(
Effect.flatMap((svc) => svc.getTeamsWithPerms(session?.user?.email))
)
),
AppRuntime.runPromise(
ScoutingService.pipe(Effect.flatMap((svc) => svc.getScoutingTeams()))
),
scoutingTool(),
]
);
Expand Down
18 changes: 12 additions & 6 deletions src/app/[team]/scrim/[scrimId]/map/[mapId]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,10 @@ import { MapTabsSkeleton } from "@/components/map/map-tabs-skeleton";
import { Suspense, ViewTransition } from "react";
import { UserNav } from "@/components/user-nav";
import { VodOverview } from "@/components/vods/vod-overview";
import { getMostPlayedHeroes } from "@/data/player-dto";
import { getUser } from "@/data/user-dto";
import { PlayerService } from "@/data/player";
import { Effect } from "effect";
import { AppRuntime } from "@/data/runtime";
import { UserService } from "@/data/user";
import { auth } from "@/lib/auth";
import {
aiChat,
Expand Down Expand Up @@ -95,7 +97,9 @@ export default async function MapDashboardPage(
const id = parseInt(params.mapId);
const mapDataId = await resolveMapDataId(id);
const session = await auth();
const user = await getUser(session?.user?.email);
const user = await AppRuntime.runPromise(
UserService.pipe(Effect.flatMap((svc) => svc.getUser(session?.user?.email)))
);
const t = await getTranslations("mapPage");

// Tournament context for back navigation
Expand All @@ -120,7 +124,9 @@ export default async function MapDashboardPage(
tournamentEnabled,
coachingCanvasEnabled,
] = await Promise.all([
getMostPlayedHeroes(id),
AppRuntime.runPromise(
PlayerService.pipe(Effect.flatMap((svc) => svc.getMostPlayedHeroes(id)))
),
prisma.matchStart.findFirst({
where: { MapDataId: mapDataId },
select: { map_name: true, team_1_name: true },
Expand Down Expand Up @@ -282,12 +288,12 @@ export default async function MapDashboardPage(
{
value: "heatmap",
label: t("tabs.heatmap"),
content: <HeatmapTab id={id} />,
content: <HeatmapTab id={mapDataId} />,
},
{
value: "replay",
label: t("tabs.replay"),
content: <ReplayTab id={id} />,
content: <ReplayTab id={mapDataId} />,
},
]
: []),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,10 @@ import { DefaultOverview } from "@/components/player/default-overview";
import { ModeToggle } from "@/components/theme-switcher";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { UserNav } from "@/components/user-nav";
import { getMostPlayedHeroes } from "@/data/player-dto";
import { getUser } from "@/data/user-dto";
import { PlayerService } from "@/data/player";
import { Effect } from "effect";
import { AppRuntime } from "@/data/runtime";
import { UserService } from "@/data/user";
import { auth } from "@/lib/auth";
import { aiChat, dataLabeling, scoutingTool } from "@/lib/flags";
import { resolveMapDataId } from "@/lib/map-data-resolver";
Expand Down Expand Up @@ -66,7 +68,9 @@ export default async function PlayerDashboardPage(
const mapDataId = await resolveMapDataId(id);
const playerName = decodeURIComponent(params.playerId);

const mostPlayedHeroes = await getMostPlayedHeroes(id);
const mostPlayedHeroes = await AppRuntime.runPromise(
PlayerService.pipe(Effect.flatMap((svc) => svc.getMostPlayedHeroes(id)))
);

const mapName = await prisma.matchStart.findFirst({
where: {
Expand All @@ -78,7 +82,9 @@ export default async function PlayerDashboardPage(
});

const session = await auth();
const user = await getUser(session?.user?.email);
const user = await AppRuntime.runPromise(
UserService.pipe(Effect.flatMap((svc) => svc.getUser(session?.user?.email)))
);

const visibility = (await prisma.scrim.findFirst({
where: {
Expand Down
14 changes: 10 additions & 4 deletions src/app/[team]/scrim/[scrimId]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@ import {
TooltipContent,
TooltipTrigger,
} from "@/components/ui/tooltip";
import { getScrim } from "@/data/scrim-dto";
import { getUser } from "@/data/user-dto";
import { ScrimService } from "@/data/scrim";
import { Effect } from "effect";
import { AppRuntime } from "@/data/runtime";
import { UserService } from "@/data/user";
import { auth } from "@/lib/auth";
import { mapComparison, overviewCard } from "@/lib/flags";
import prisma from "@/lib/prisma";
Expand Down Expand Up @@ -76,7 +78,9 @@ export default async function ScrimDashboardPage(
const session = await auth();
const t = await getTranslations("scrimPage");

const scrim = await getScrim(id);
const scrim = await AppRuntime.runPromise(
ScrimService.pipe(Effect.flatMap((svc) => svc.getScrim(id)))
);
if (!scrim) notFound();

const teamId = scrim.teamId;
Expand All @@ -89,7 +93,9 @@ export default async function ScrimDashboardPage(
})
).sort((a, b) => a.id - b.id);

const user = await getUser(session?.user?.email);
const user = await AppRuntime.runPromise(
UserService.pipe(Effect.flatMap((svc) => svc.getUser(session?.user?.email)))
);

const isManager = teamId
? (await prisma.teamManager.findFirst({
Expand Down
14 changes: 11 additions & 3 deletions src/app/api/(email)/send-team-invite/route.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { Effect } from "effect";
import { AppRuntime } from "@/data/runtime";
import { UserService } from "@/data/user";
import TeamInviteUserEmail from "@/components/email/team-invite";
import { getUser } from "@/data/user-dto";
import { auditLog } from "@/lib/audit-logs";
import { email } from "@/lib/email";
import { createShortLink } from "@/lib/link-service";
Expand Down Expand Up @@ -35,15 +37,21 @@ export async function POST(req: NextRequest) {
});
if (!teamInviteToken) return new Response("Token not found", { status: 404 });

const inviter = await getUser(teamInviteToken?.email);
const inviter = await AppRuntime.runPromise(
UserService.pipe(
Effect.flatMap((svc) => svc.getUser(teamInviteToken?.email))
)
);
if (!inviter) return new Response("Inviter not found", { status: 404 });

const team = await prisma.team.findFirst({
where: { id: teamInviteToken.teamId },
});
if (!team) return new Response("Team not found", { status: 404 });

const user = await getUser(inviteeEmail);
const user = await AppRuntime.runPromise(
UserService.pipe(Effect.flatMap((svc) => svc.getUser(inviteeEmail)))
);
if (!user) return new Response("User not found", { status: 404 });

const shortLink = await createShortLink(
Expand Down
Loading
Loading