History

TanStack Start SPA mode + catalog deps + Vite 8 (#89)

- Cloud app uses TanStack Start with SPA mode for unified dev/prod - File-based routes: pages, /v1/* API catch-all, /auth/* catch-all - Root route with auth gate + ExecutorProvider - Cloud-specific auth API group (CloudAuthApi) with typed atom - Upgrade Vite to v8, @vitejs/plugin-react to v6 across workspace - Catalog shared deps (vite, react, typescript, tanstack, tailwind) - Fix Tailwind @source paths for new package structure - Cloud shell with user footer, no version check

Rhys Sullivan committed 7 months ago

Commit 3adcf112 parents 4153df4 9fe573868 files · +1340 −1305Browse files

Unified · Split

68 files
  1. .gitignore +1 −1
  2. .gitmodules +9 −0
  3. .reference/executor +0 −1
  4. .reference/tanstack-router +1 −0
  5. apps/cli/package.json +1 −1
  6. apps/cloud/index.html +0 −15
  7. apps/cloud/package.json +13 −13
  8. apps/cloud/src/api.ts +19 −7
  9. apps/cloud/src/auth/api.ts +19 −1
  10. apps/cloud/src/auth/context.ts +46 −4
  11. apps/cloud/src/auth/handlers.ts +95 −21
  12. apps/cloud/src/auth/workos.ts +94 −105
  13. apps/cloud/src/handlers/auth.ts +0 −143
  14. apps/cloud/src/handlers/teams.ts +0 −81
  15. apps/cloud/src/main.ts +0 −99
  16. apps/cloud/src/routeTree.gen.ts +198 −0
  17. apps/cloud/src/router.tsx +10 −0
  18. apps/cloud/src/routes/__root.tsx +69 −0
  19. apps/cloud/src/routes/index.tsx +6 −0
  20. apps/cloud/src/routes/secrets.tsx +6 −0
  21. apps/cloud/src/routes/sources.$namespace.tsx +9 −0
  22. apps/cloud/src/routes/sources.add.$pluginKey.tsx +19 −0
  23. apps/cloud/src/routes/tools.tsx +6 −0
  24. apps/cloud/src/routes/v1.$.ts +14 −0
  25. apps/cloud/src/server/api-handler.ts +9 −0
  26. apps/cloud/src/vite-env.d.ts +1 −0
  27. apps/cloud/src/web/App.tsx +0 −29
  28. apps/cloud/src/web/main.tsx +0 −7
  29. apps/cloud/src/web/router.tsx +0 −93
  30. apps/cloud/src/web/shell.tsx +14 −227
  31. apps/cloud/tsconfig.json +2 −2
  32. apps/cloud/vite.config.ts +11 −14
  33. apps/desktop/package.json +1 −1
  34. apps/local/index.html +0 −15
  35. apps/local/package.json +12 −11
  36. apps/local/src/routeTree.gen.ts +198 −0
  37. apps/local/src/router.tsx +10 −0
  38. apps/local/src/routes/__root.tsx +45 −0
  39. apps/local/src/routes/index.tsx +6 −0
  40. apps/local/src/routes/mcp.$.ts +13 −0
  41. apps/local/src/routes/secrets.tsx +6 −0
  42. apps/local/src/routes/sources.$namespace.tsx +9 −0
  43. apps/local/src/routes/sources.add.$pluginKey.tsx +19 −0
  44. apps/local/src/routes/tools.tsx +6 −0
  45. apps/local/src/routes/v1.$.ts +14 −0
  46. apps/local/src/server/api-handler.ts +29 −0
  47. apps/local/src/server/dev-backend.ts +0 −17
  48. apps/local/src/vite-env.d.ts +1 −0
  49. apps/local/src/web/App.tsx +0 −6
  50. apps/local/src/web/main.tsx +0 −7
  51. apps/local/src/web/router.tsx +0 −93
  52. apps/local/src/web/shell.tsx +0 −1
  53. apps/local/vite.config.ts +18 −181
  54. bun.lock +235 −73
  55. package.json +12 −1
  56. packages/core/api/package.json +1 −1
  57. packages/core/config/package.json +1 −1
  58. packages/core/sdk/package.json +1 −1
  59. packages/core/storage-file/package.json +1 −1
  60. packages/core/storage-postgres/package.json +1 −1
  61. packages/plugins/google-discovery/package.json +4 −4
  62. packages/plugins/graphql/package.json +4 −4
  63. packages/plugins/mcp/package.json +4 −4
  64. packages/plugins/onepassword/package.json +2 −2
  65. packages/plugins/openapi/package.json +4 −4
  66. packages/react/package.json +4 −4
  67. packages/react/src/components/mcp-install-card.tsx +3 −3
  68. packages/react/src/styles/globals.css +4 −5
.gitignore+1−1
@@ -42,4 +42,4 @@ executor.har · 41 unmodified lines
4242 apps/desktop/resources/
4343
4444 # cloud local dev database
45−.pglite
45+.pglite
.gitmodules+9−0
@@ -0,0 +1,9 @@
1+[submodule ".reference/effect-atom"]
2+ path = .reference/effect-atom
3+ url = https://github.com/tim-smart/effect-atom.git
4+[submodule ".reference/tanstack-router"]
5+ path = .reference/tanstack-router
6+ url = https://github.com/TanStack/router.git
7+[submodule ".reference/effect"]
8+ path = .reference/effect
9+ url = https://github.com/Effect-TS/effect.git
.reference/executor+0−1
@@ -1 +0,0 @@
1−Subproject commit 2d532f8322368eedc835fa09dc9223a9ddef9e1d
.reference/tanstack-router+1−0
@@ -0,0 +1 @@
1+Subproject commit 5a81726f0a2f819fae0763896cef784aa10ddc9f
apps/cli/package.json+1−1
@@ -30,6 +30,6 @@ · 29 unmodified lines
3030 },
3131 "devDependencies": {
3232 "bun-types": "catalog:",
33− "typescript": "^5.9.3"
33+ "typescript": "catalog:"
3434 }
3535 }
apps/cloud/index.html+0−15
@@ -1,15 +0,0 @@
1−<!doctype html>
2−<html lang="en">
3− <head>
4− <meta charset="UTF-8" />
5− <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6− <title>Executor Cloud</title>
7− <link rel="preconnect" href="https://fonts.googleapis.com" />
8− <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
9− <link href="https://fonts.googleapis.com/css2?family=DM+Sans:ital,opsz,wght@0,9..40,300..700;1,9..40,300..700&family=Instrument+Serif&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet" />
10− </head>
11− <body>
12− <div id="root"></div>
13− <script type="module" src="/src/web/main.tsx"></script>
14− </body>
15−</html>
apps/cloud/package.json+13−13
@@ -15,30 +15,30 @@ · 14 unmodified lines
1515 "@executor/react": "workspace:*",
1616 "@executor/sdk": "workspace:*",
1717 "@executor/storage-postgres": "workspace:*",
18− "@tanstack/react-router": "^1.168.10",
18+ "@tanstack/react-router": "catalog:",
19+ "@tanstack/react-start": "catalog:",
1920 "@workos-inc/node": "^7.0.0",
2021 "drizzle-orm": "catalog:",
2122 "effect": "catalog:",
2223 "pg": "^8.16.0",
23− "react": "^19.1.0",
24− "react-dom": "^19.1.0"
24+ "react": "catalog:",
25+ "react-dom": "catalog:"
2526 },
2627 "devDependencies": {
2728 "@electric-sql/pglite": "^0.4.3",
29+ "@tailwindcss/vite": "catalog:",
2830 "@types/pg": "^8.15.4",
29− "@tailwindcss/vite": "^4.1.10",
30− "@types/react": "^19.1.0",
31− "@types/react-dom": "^19.1.0",
32− "@vitejs/plugin-react": "^4.5.2",
31+ "@types/react": "catalog:",
32+ "@types/react-dom": "catalog:",
33+ "@vitejs/plugin-react": "catalog:",
3334 "portless": "^0.3.0",
34− "typescript": "^5.9.3",
35− "vite": "^6.3.5"
35+ "typescript": "catalog:",
36+ "vite": "catalog:"
3637 },
3738 "scripts": {
38− "dev": "op run --env-file=.env -- portless executor-cloud bun --hot ./src/main.ts",
39− "dev:web": "vite",
40− "start": "bun ./src/main.ts",
41− "build:web": "vite build",
39+ "dev": "portless executor-cloud op run --env-file=.env -- vite dev",
40+ "build": "vite build",
41+ "start": "bun ./server.ts",
4242 "typecheck": "tsc --noEmit"
4343 }
4444 }
apps/cloud/src/api.ts+19−7
@@ -12,17 +12,16 @@ import { Effect, Layer } from "effect"; · 11 unmodified lines
1212
1313 import { addGroup, CoreHandlers, ExecutorService, ExecutionEngineService } from "@executor/api";
1414 import { createExecutionEngine } from "@executor/execution";
15−import { makeUserStore } from "@executor/storage-postgres";
1615 import { OpenApiGroup, OpenApiExtensionService, OpenApiHandlers } from "@executor/plugin-openapi/api";
1716 import { McpGroup, McpExtensionService, McpHandlers } from "@executor/plugin-mcp/api";
1817 import { GoogleDiscoveryGroup, GoogleDiscoveryExtensionService, GoogleDiscoveryHandlers } from "@executor/plugin-google-discovery/api";
1918 import { GraphqlGroup, GraphqlExtensionService, GraphqlHandlers } from "@executor/plugin-graphql/api";
2019
2120 import { createTeamExecutor } from "./services/executor";
22−import { authenticateRequest } from "./auth/workos";
2321 import { CloudAuthApi } from "./auth/api";
2422 import { CloudAuthHandlers } from "./auth/handlers";
2523 import { AuthContext, UserStoreService } from "./auth/context";
24+import { WorkOSAuth } from "./auth/workos";
2625 import type { DrizzleDb } from "./services/db";
2726
2827 // ---------------------------------------------------------------------------
@@ -65,10 +64,15 @@ const parseCookie = (cookieHeader: string | null, name: string): string | null = · 36 unmodified lines
6564 // ---------------------------------------------------------------------------
6665
6766 export const createCloudApiHandler = (db: DrizzleDb, encryptionKey: string) => {
68− const userStore = makeUserStore(db);
69−
7067 return async (request: Request): Promise<Response> => {
71− const auth = await authenticateRequest(request);
68+ // Authenticate via WorkOS sealed session
69+ const auth = await Effect.runPromise(
70+ Effect.gen(function* () {
71+ const workos = yield* WorkOSAuth;
72+ return yield* workos.authenticateRequest(request);
73+ }).pipe(Effect.provide(WorkOSAuth.Default)),
74+ );
75+
7276 if (!auth) {
7377 return Response.json({ error: "Unauthorized" }, { status: 401 });
7478 }
@@ -78,7 +82,14 @@ export const createCloudApiHandler = (db: DrizzleDb, encryptionKey: string) => { · 3 unmodified lines
7882 return Response.json({ error: "No team selected" }, { status: 401 });
7983 }
8084
81− const team = await userStore.getTeam(teamId);
85+ // Resolve team name
86+ const userStore = UserStoreService.layer(db);
87+ const team = await Effect.runPromise(
88+ Effect.gen(function* () {
89+ const users = yield* UserStoreService;
90+ return yield* users.use((s) => s.getTeam(teamId));
91+ }).pipe(Effect.provide(userStore)),
92+ );
8293 const teamName = team?.name ?? "Unknown Team";
8394
8495 const executor = await Effect.runPromise(
@@ -108,7 +119,8 @@ export const createCloudApiHandler = (db: DrizzleDb, encryptionKey: string) => { · 23 unmodified lines
108119 name: `${auth.firstName ?? ""} ${auth.lastName ?? ""}`.trim() || null,
109120 avatarUrl: auth.avatarUrl,
110121 })),
111− Layer.provideMerge(Layer.succeed(UserStoreService, userStore)),
122+ Layer.provideMerge(UserStoreService.layer(db)),
123+ Layer.provideMerge(WorkOSAuth.Default),
112124 Layer.provideMerge(HttpServer.layerContext),
113125 ),
114126 { middleware: HttpMiddleware.logger },
apps/cloud/src/auth/api.ts+19−1
@@ -1,5 +1,6 @@
11 import { HttpApiEndpoint, HttpApiGroup } from "@effect/platform";
22 import { Schema } from "effect";
3+import { UserStoreError, WorkOSError } from "./context";
34
45 const AuthUser = Schema.Struct({
56 id: Schema.String,
@@ -18,8 +19,25 @@ const AuthMeResponse = Schema.Struct({ · 12 unmodified lines
1819 team: Schema.NullOr(AuthTeam),
1920 });
2021
22+const AuthCallbackSearch = Schema.Struct({
23+ code: Schema.String,
24+});
25+
2126 export class CloudAuthApi extends HttpApiGroup.make("cloudAuth")
2227 .add(
2328 HttpApiEndpoint.get("me")`/auth/me`
24− .addSuccess(AuthMeResponse),
29+ .addSuccess(AuthMeResponse)
30+ .addError(UserStoreError),
31+ )
32+ .add(
33+ HttpApiEndpoint.get("login")`/auth/login`,
34+ )
35+ .add(
36+ HttpApiEndpoint.get("callback")`/auth/callback`
37+ .setUrlParams(AuthCallbackSearch)
38+ .addError(UserStoreError)
39+ .addError(WorkOSError),
40+ )
41+ .add(
42+ HttpApiEndpoint.post("logout")`/auth/logout`,
2543 ) {}
apps/cloud/src/auth/context.ts+46−4
@@ -1,5 +1,24 @@
1−import { Context } from "effect";
2−import type { makeUserStore } from "@executor/storage-postgres";
1+import { Context, Effect, Layer, Schema } from "effect";
2+import { makeUserStore } from "@executor/storage-postgres";
3+import type { DrizzleDb } from "../services/db";
4+
5+// ---------------------------------------------------------------------------
6+// Errors
7+// ---------------------------------------------------------------------------
8+
9+export class UserStoreError extends Schema.TaggedError<UserStoreError>()(
10+ "UserStoreError",
11+ { cause: Schema.Unknown },
12+) {}
13+
14+export class WorkOSError extends Schema.TaggedError<WorkOSError>()(
15+ "WorkOSError",
16+ { cause: Schema.Unknown },
17+) {}
18+
19+// ---------------------------------------------------------------------------
20+// AuthContext — resolved per-request from sealed session
21+// ---------------------------------------------------------------------------
322
423 export class AuthContext extends Context.Tag("@executor/cloud/AuthContext")<
524 AuthContext,
@@ -12,7 +31,30 @@ export class AuthContext extends Context.Tag("@executor/cloud/AuthContext")< · 6 unmodified lines
1231 }
1332 >() {}
1433
34+// ---------------------------------------------------------------------------
35+// UserStoreService — wraps the Drizzle-backed user store with Effect
36+// ---------------------------------------------------------------------------
37+
38+type RawStore = ReturnType<typeof makeUserStore>;
39+
40+const makeService = (db: DrizzleDb) => {
41+ const store = makeUserStore(db);
42+
43+ const use = <A>(fn: (s: RawStore) => Promise<A>) =>
44+ Effect.tryPromise({
45+ try: () => fn(store),
46+ catch: (cause) => new UserStoreError({ cause }),
47+ }).pipe(Effect.withSpan("user_store"));
48+
49+ return { use };
50+};
51+
52+type UserStoreServiceType = ReturnType<typeof makeService>;
53+
1554 export class UserStoreService extends Context.Tag("@executor/cloud/UserStoreService")<
1655 UserStoreService,
17− ReturnType<typeof makeUserStore>
18−>() {}
56+ UserStoreServiceType
57+>() {
58+ static layer = (db: DrizzleDb) =>
59+ Layer.succeed(this, makeService(db));
60+}
apps/cloud/src/auth/handlers.ts+95−21
@@ -1,9 +1,10 @@
1−import { HttpApiBuilder } from "@effect/platform";
1+import { HttpApiBuilder, HttpServerResponse } from "@effect/platform";
22 import { Effect } from "effect";
33
44 import { addGroup } from "@executor/api";
55 import { CloudAuthApi } from "./api";
66 import { AuthContext, UserStoreService } from "./context";
7+import { WorkOSAuth, makeSessionCookie, clearSessionCookie } from "./workos";
78
89 const ApiWithCloudAuth = addGroup(CloudAuthApi);
910
@@ -11,24 +12,97 @@ export const CloudAuthHandlers = HttpApiBuilder.group( · 1 unmodified line
1112 ApiWithCloudAuth,
1213 "cloudAuth",
1314 (handlers) =>
14− handlers.handle("me", () =>
15− Effect.gen(function* () {
16− const auth = yield* AuthContext;
17− const userStore = yield* UserStoreService;
18−
19− const team = yield* Effect.tryPromise(() =>
20− userStore.getTeam(auth.teamId),
21− ).pipe(Effect.orDie);
22−
23− return {
24− user: {
25− id: auth.userId,
26− email: auth.email,
27− name: auth.name,
28− avatarUrl: auth.avatarUrl,
29− },
30− team: team ? { id: team.id, name: team.name } : null,
31− };
32− }),
33− ),
15+ handlers
16+ .handle("me", () =>
17+ Effect.gen(function* () {
18+ const auth = yield* AuthContext;
19+ const users = yield* UserStoreService;
20+ const team = yield* users.use((s) => s.getTeam(auth.teamId));
21+
22+ return {
23+ user: {
24+ id: auth.userId,
25+ email: auth.email,
26+ name: auth.name,
27+ avatarUrl: auth.avatarUrl,
28+ },
29+ team: team ? { id: team.id, name: team.name } : null,
30+ };
31+ }),
32+ )
33+ .handleRaw("login", () =>
34+ Effect.gen(function* () {
35+ const workos = yield* WorkOSAuth;
36+ const baseUrl = process.env.APP_URL ?? `http://localhost:${process.env.PORT ?? "3000"}`;
37+ const url = workos.getAuthorizationUrl(`${baseUrl}/auth/callback`);
38+ return HttpServerResponse.redirect(url, { status: 302 });
39+ }),
40+ )
41+ .handleRaw("callback", ({ urlParams }) =>
42+ Effect.gen(function* () {
43+ const workos = yield* WorkOSAuth;
44+ const users = yield* UserStoreService;
45+
46+ const result = yield* workos.authenticateWithCode(urlParams.code);
47+ const workosUser = result.user;
48+
49+ const user = yield* users.use((s) =>
50+ s.upsertUser({
51+ id: workosUser.id,
52+ email: workosUser.email,
53+ name: `${workosUser.firstName ?? ""} ${workosUser.lastName ?? ""}`.trim() || undefined,
54+ avatarUrl: workosUser.profilePictureUrl ?? undefined,
55+ }),
56+ );
57+
58+ const resolveTeam = Effect.gen(function* () {
59+ const pending = yield* users.use((s) => s.getPendingInvitations(user.email));
60+ if (pending.length > 0) {
61+ const invitation = pending[0]!;
62+ yield* users.use((s) => s.acceptInvitation(invitation.id));
63+ yield* users.use((s) => s.addMember(invitation.teamId, user.id, "member"));
64+ return invitation.teamId;
65+ }
66+
67+ const teams = yield* users.use((s) => s.getTeamsForUser(user.id));
68+ if (teams.length > 0) return teams[0]!.teamId;
69+
70+ const team = yield* users.use((s) =>
71+ s.createTeam(`${user.name ?? user.email}'s Team`),
72+ );
73+ yield* users.use((s) => s.addMember(team.id, user.id, "owner"));
74+ return team.id;
75+ });
76+
77+ const teamId = yield* resolveTeam;
78+
79+ const sealedSession = result.sealedSession;
80+ if (!sealedSession) {
81+ return HttpServerResponse.text("Failed to create session", { status: 500 });
82+ }
83+
84+ return HttpServerResponse.redirect("/", {
85+ status: 302,
86+ headers: {
87+ "Set-Cookie": [
88+ makeSessionCookie(sealedSession),
89+ `executor_team=${teamId}; Path=/; HttpOnly; SameSite=Lax; Max-Age=604800`,
90+ ].join(", "),
91+ },
92+ });
93+ }),
94+ )
95+ .handleRaw("logout", () =>
96+ Effect.succeed(
97+ HttpServerResponse.redirect("/", {
98+ status: 302,
99+ headers: {
100+ "Set-Cookie": [
101+ clearSessionCookie(),
102+ "executor_team=; Path=/; HttpOnly; SameSite=Lax; Max-Age=0",
103+ ].join(", "),
104+ },
105+ }),
106+ ),
107+ ),
34108 );
apps/cloud/src/auth/workos.ts+94−105
@@ -1,119 +1,108 @@
11 // ---------------------------------------------------------------------------
2−// WorkOS AuthKit integration — sealed sessions, no server-side session store
2+// WorkOS AuthKit — Effect-native sealed session management
33 // ---------------------------------------------------------------------------
44
5+import { Context, Effect, Layer } from "effect";
56 import { WorkOS } from "@workos-inc/node";
7+import { WorkOSError } from "./context";
68
79 const COOKIE_NAME = "wos-session";
810
9−let workos: WorkOS | null = null;
10−
11−export const getWorkOS = (): WorkOS => {
12− if (!workos) {
13− workos = new WorkOS(process.env.WORKOS_API_KEY!);
14− }
15− return workos;
16−};
17−
18−const getCookiePassword = (): string => {
19− const password = process.env.WORKOS_COOKIE_PASSWORD;
20− if (!password || password.length < 32) {
21− throw new Error("WORKOS_COOKIE_PASSWORD must be at least 32 characters");
22− }
23− return password;
24−};
25−
26−export const getAuthorizationUrl = (redirectUri: string): string => {
27− const wos = getWorkOS();
28− return wos.userManagement.getAuthorizationUrl({
29− provider: "authkit",
30− redirectUri,
31− clientId: process.env.WORKOS_CLIENT_ID!,
32− });
33−};
11+// ---------------------------------------------------------------------------
12+// Service
13+// ---------------------------------------------------------------------------
3414
35−export const authenticateWithCode = async (code: string) => {
36− const wos = getWorkOS();
37− return wos.userManagement.authenticateWithCode({
38− code,
39− clientId: process.env.WORKOS_CLIENT_ID!,
40− session: {
41− sealSession: true,
42− cookiePassword: getCookiePassword(),
43− },
44− });
45−};
4615
47−/**
48− * Authenticate a request using the sealed session cookie.
49− * Returns user info or null if not authenticated.
50− */
51−/**
52− * Authenticate a request using the sealed session cookie.
53− * Automatically refreshes expired tokens and returns a new cookie if needed.
54− */
55−export const authenticateRequest = async (request: Request) => {
56− const cookieHeader = request.headers.get("cookie");
57− const sessionData = parseCookie(cookieHeader, COOKIE_NAME);
58− if (!sessionData) return null;
59−
60− const wos = getWorkOS();
61− const session = wos.userManagement.loadSealedSession({
62− sessionData,
63− cookiePassword: getCookiePassword(),
64− });
65−
66− const result = await session.authenticate();
67−
68− if (result.authenticated) {
69− return {
70− userId: result.user.id,
71− email: result.user.email,
72− firstName: result.user.firstName,
73− lastName: result.user.lastName,
74− avatarUrl: result.user.profilePictureUrl,
75− sessionId: result.sessionId,
76− refreshedCookie: undefined as string | undefined,
77− };
78− }
16+const make = Effect.gen(function* () {
17+ const apiKey = process.env.WORKOS_API_KEY!;
18+ const clientId = process.env.WORKOS_CLIENT_ID!;
19+ const cookiePassword = process.env.WORKOS_COOKIE_PASSWORD!;
7920
80− // Token expired — try refreshing
81− if (result.reason === "no_session_cookie_provided") return null;
82−
83− try {
84− const refreshed = await session.refresh();
85− if (!refreshed.authenticated || !refreshed.sealedSession) return null;
86−
87− return {
88− userId: refreshed.user.id,
89− email: refreshed.user.email,
90− firstName: refreshed.user.firstName,
91− lastName: refreshed.user.lastName,
92− avatarUrl: refreshed.user.profilePictureUrl,
93− sessionId: refreshed.sessionId,
94− refreshedCookie: makeSessionCookie(refreshed.sealedSession),
95− };
96− } catch {
97− return null;
21+ if (!cookiePassword || cookiePassword.length < 32) {
22+ return yield* Effect.die(new Error("WORKOS_COOKIE_PASSWORD must be at least 32 characters"));
9823 }
99−};
10024
101−/**
102− * Get logout URL for the current session.
103− */
104−export const getLogoutUrl = async (request: Request) => {
105− const cookieHeader = request.headers.get("cookie");
106− const sessionData = parseCookie(cookieHeader, COOKIE_NAME);
107− if (!sessionData) return null;
108−
109− const wos = getWorkOS();
110− const session = wos.userManagement.loadSealedSession({
111− sessionData,
112− cookiePassword: getCookiePassword(),
113− });
114−
115− return session.getLogoutUrl();
116−};
25+ const workos = new WorkOS(apiKey, { clientId });
26+
27+ const use = <A>(fn: (wos: WorkOS) => Promise<A>) =>
28+ Effect.tryPromise({
29+ try: () => fn(workos),
30+ catch: (cause) => new WorkOSError({ cause }),
31+ }).pipe(Effect.withSpan("workos"));
32+
33+ return {
34+ getAuthorizationUrl: (redirectUri: string) =>
35+ workos.userManagement.getAuthorizationUrl({
36+ provider: "authkit",
37+ redirectUri,
38+ clientId,
39+ }),
40+
41+ authenticateWithCode: (code: string) =>
42+ use((wos) =>
43+ wos.userManagement.authenticateWithCode({
44+ code,
45+ clientId,
46+ session: { sealSession: true, cookiePassword },
47+ }),
48+ ),
49+
50+ authenticateRequest: (request: Request) =>
51+ Effect.gen(function* () {
52+ const sessionData = parseCookie(request.headers.get("cookie"), COOKIE_NAME);
53+ if (!sessionData) return null;
54+
55+ const session = workos.userManagement.loadSealedSession({
56+ sessionData,
57+ cookiePassword,
58+ });
59+
60+ const result = yield* use((wos) => session.authenticate());
61+
62+ if (result.authenticated) {
63+ return {
64+ userId: result.user.id,
65+ email: result.user.email,
66+ firstName: result.user.firstName,
67+ lastName: result.user.lastName,
68+ avatarUrl: result.user.profilePictureUrl,
69+ sessionId: result.sessionId,
70+ refreshedCookie: undefined as string | undefined,
71+ };
72+ }
73+
74+ if (result.reason === "no_session_cookie_provided") return null;
75+
76+ // Try refreshing
77+ const refreshed = yield* use((wos) => session.refresh()).pipe(
78+ Effect.orElseSucceed(() => ({ authenticated: false as const })),
79+ );
80+
81+ if (!refreshed.authenticated || !("sealedSession" in refreshed) || !refreshed.sealedSession) return null;
82+
83+ return {
84+ userId: refreshed.user.id,
85+ email: refreshed.user.email,
86+ firstName: refreshed.user.firstName,
87+ lastName: refreshed.user.lastName,
88+ avatarUrl: refreshed.user.profilePictureUrl,
89+ sessionId: refreshed.sessionId,
90+ refreshedCookie: makeSessionCookie(refreshed.sealedSession),
91+ };
92+ }),
93+ };
94+});
95+
96+type WorkOSAuthService = Effect.Effect.Success<typeof make>;
97+
98+export class WorkOSAuth extends Context.Tag("@executor/cloud/WorkOSAuth")<
99+ WorkOSAuth,
100+ WorkOSAuthService
101+>() {
102+ static Default = Layer.effect(this, make).pipe(
103+ Layer.annotateSpans({ module: "WorkOSAuth" }),
104+ );
105+}
117106
118107 // ---------------------------------------------------------------------------
119108 // Cookie helpers
@@ -125,7 +114,7 @@ export const makeSessionCookie = (sealedSession: string): string => { · 5 unmodified lines
125114 "Path=/",
126115 "HttpOnly",
127116 "SameSite=Lax",
128− "Max-Age=604800", // 7 days
117+ "Max-Age=604800",
129118 ];
130119 if (process.env.NODE_ENV === "production") parts.push("Secure");
131120 return parts.join("; ");
apps/cloud/src/handlers/auth.ts+0−143
@@ -1,143 +0,0 @@
1−// ---------------------------------------------------------------------------
2−// Auth handlers — login, callback, logout, me
3−// ---------------------------------------------------------------------------
4−
5−import { makeUserStore } from "@executor/storage-postgres";
6−import {
7− getAuthorizationUrl,
8− authenticateWithCode,
9− authenticateRequest,
10− getLogoutUrl,
11− makeSessionCookie,
12− clearSessionCookie,
13−} from "../auth/workos";
14−import type { DrizzleDb } from "../services/db";
15−
16−export const createAuthHandlers = (db: DrizzleDb) => {
17− const userStore = makeUserStore(db);
18−
19− const getBaseUrl = (): string => {
20− if (process.env.APP_URL) return process.env.APP_URL;
21− const port = process.env.PORT ?? "3000";
22− return `http://localhost:${port}`;
23− };
24−
25− return {
26− login: async (_request: Request): Promise<Response> => {
27− const redirectUri = `${getBaseUrl()}/auth/callback`;
28− const url = getAuthorizationUrl(redirectUri);
29− return Response.redirect(url, 302);
30− },
31−
32− callback: async (request: Request): Promise<Response> => {
33− const url = new URL(request.url);
34− const code = url.searchParams.get("code");
35− if (!code) {
36− return new Response("Missing code parameter", { status: 400 });
37− }
38−
39− try {
40− const result = await authenticateWithCode(code);
41− const workosUser = result.user;
42−
43− // Upsert user
44− const user = await userStore.upsertUser({
45− id: workosUser.id,
46− email: workosUser.email,
47− name: `${workosUser.firstName ?? ""} ${workosUser.lastName ?? ""}`.trim() || undefined,
48− avatarUrl: workosUser.profilePictureUrl ?? undefined,
49− });
50−
51− // Check for pending invitations
52− const pendingInvitations = await userStore.getPendingInvitations(user.email);
53− let teamId: string;
54−
55− if (pendingInvitations.length > 0) {
56− const invitation = pendingInvitations[0]!;
57− await userStore.acceptInvitation(invitation.id);
58− await userStore.addMember(invitation.teamId, user.id, "member");
59− teamId = invitation.teamId;
60− } else {
61− const teams = await userStore.getTeamsForUser(user.id);
62− if (teams.length > 0) {
63− teamId = teams[0]!.teamId;
64− } else {
65− const team = await userStore.createTeam(`${user.name ?? user.email}'s Team`);
66− await userStore.addMember(team.id, user.id, "owner");
67− teamId = team.id;
68− }
69− }
70−
71− // Store teamId in a separate cookie (WorkOS sealed session doesn't carry app-specific data)
72− const sealedSession = result.sealedSession;
73− if (!sealedSession) {
74− return new Response("Failed to create session", { status: 500 });
75− }
76−
77− return new Response(null, {
78− status: 302,
79− headers: [
80− ["Location", "/"],
81− ["Set-Cookie", makeSessionCookie(sealedSession)],
82− ["Set-Cookie", `executor_team=${teamId}; Path=/; HttpOnly; SameSite=Lax; Max-Age=604800`],
83− ],
84− });
85− } catch (error) {
86− console.error("Auth callback error:", error);
87− return new Response("Authentication failed", { status: 500 });
88− }
89− },
90−
91− logout: async (request: Request): Promise<Response> => {
92− const logoutUrl = await getLogoutUrl(request);
93− const headers: [string, string][] = [
94− ["Set-Cookie", clearSessionCookie()],
95− ["Set-Cookie", "executor_team=; Path=/; HttpOnly; SameSite=Lax; Max-Age=0"],
96− ];
97−
98− if (logoutUrl) {
99− headers.push(["Location", logoutUrl]);
100− return new Response(null, { status: 302, headers });
101− }
102−
103− headers.push(["Location", "/login"]);
104− return new Response(null, { status: 302, headers });
105− },
106−
107− me: async (request: Request): Promise<Response> => {
108− const auth = await authenticateRequest(request);
109− if (!auth) {
110− return Response.json({ error: "Not authenticated" }, { status: 401 });
111− }
112−
113− const user = await userStore.getUser(auth.userId);
114− if (!user) {
115− return Response.json({ error: "User not found" }, { status: 401 });
116− }
117−
118− // Read teamId from cookie
119− const teamId = parseCookie(request.headers.get("cookie"), "executor_team");
120− const team = teamId ? await userStore.getTeam(teamId) : null;
121−
122− return Response.json({
123− user: {
124− id: user.id,
125− email: user.email,
126− name: user.name,
127− avatarUrl: user.avatarUrl,
128− },
129− team: team ? { id: team.id, name: team.name } : null,
130− });
131− },
132− };
133−};
134−
135−const parseCookie = (cookieHeader: string | null, name: string): string | null => {
136− if (!cookieHeader) return null;
137− const match = cookieHeader
138− .split(";")
139− .map((c) => c.trim())
140− .find((c) => c.startsWith(`${name}=`));
141− if (!match) return null;
142− return match.slice(name.length + 1) || null;
143−};
apps/cloud/src/handlers/teams.ts+0−81
@@ -1,81 +0,0 @@
1−// ---------------------------------------------------------------------------
2−// Team handlers — members, invitations
3−// ---------------------------------------------------------------------------
4−
5−import { makeUserStore } from "@executor/storage-postgres";
6−import { authenticateRequest } from "../auth/workos";
7−import type { DrizzleDb } from "../services/db";
8−
9−const parseCookie = (cookieHeader: string | null, name: string): string | null => {
10− if (!cookieHeader) return null;
11− const match = cookieHeader
12− .split(";")
13− .map((c) => c.trim())
14− .find((c) => c.startsWith(`${name}=`));
15− if (!match) return null;
16− return match.slice(name.length + 1) || null;
17−};
18−
19−export const createTeamHandlers = (db: DrizzleDb) => {
20− const userStore = makeUserStore(db);
21−
22− const requireAuth = async (request: Request) => {
23− const auth = await authenticateRequest(request);
24− if (!auth) return null;
25− const teamId = parseCookie(request.headers.get("cookie"), "executor_team");
26− if (!teamId) return null;
27− return { ...auth, teamId };
28− };
29−
30− return {
31− listMembers: async (request: Request): Promise<Response> => {
32− const auth = await requireAuth(request);
33− if (!auth) return Response.json({ error: "Unauthorized" }, { status: 401 });
34−
35− const members = await userStore.listMembers(auth.teamId);
36− return Response.json({ members });
37− },
38−
39− invite: async (request: Request): Promise<Response> => {
40− const auth = await requireAuth(request);
41− if (!auth) return Response.json({ error: "Unauthorized" }, { status: 401 });
42−
43− const body = await request.json() as { email: string };
44− if (!body.email) {
45− return Response.json({ error: "Email required" }, { status: 400 });
46− }
47−
48− const invitation = await userStore.createInvitation(
49− auth.teamId,
50− body.email,
51− auth.userId,
52− );
53− return Response.json({ invitation });
54− },
55−
56− listInvitations: async (request: Request): Promise<Response> => {
57− const auth = await requireAuth(request);
58− if (!auth) return Response.json({ error: "Unauthorized" }, { status: 401 });
59−
60− const invitations = await userStore.getTeamInvitations(auth.teamId);
61− return Response.json({ invitations });
62− },
63−
64− removeMember: async (request: Request): Promise<Response> => {
65− const auth = await requireAuth(request);
66− if (!auth) return Response.json({ error: "Unauthorized" }, { status: 401 });
67−
68− const body = await request.json() as { userId: string };
69− if (!body.userId) {
70− return Response.json({ error: "userId required" }, { status: 400 });
71− }
72−
73− if (body.userId === auth.userId) {
74− return Response.json({ error: "Cannot remove yourself" }, { status: 400 });
75− }
76−
77− await userStore.removeMember(auth.teamId, body.userId);
78− return Response.json({ removed: true });
79− },
80− };
81−};
apps/cloud/src/main.ts+0−99
@@ -1,99 +0,0 @@
1−// ---------------------------------------------------------------------------
2−// Executor Cloud — main entry point
3−//
4−// Single Bun.serve() routing:
5−// /auth/* → Auth handlers (login, callback, logout, me)
6−// /api/team/* → Team handlers (members, invitations)
7−// /v1/* → Effect HTTP API (tools, sources, secrets, executions)
8−// /docs → OpenAPI docs
9−// /* → Static frontend (SPA)
10−// ---------------------------------------------------------------------------
11−
12−import { resolve } from "node:path";
13−import { getDb } from "./services/db";
14−import { createAuthHandlers } from "./handlers/auth";
15−import { createTeamHandlers } from "./handlers/teams";
16−import { createCloudApiHandler } from "./api";
17−
18−const PORT = parseInt(process.env.PORT ?? "3000", 10);
19−const ENCRYPTION_KEY = process.env.ENCRYPTION_KEY ?? "local-dev-encryption-key";
20−
21−// ---------------------------------------------------------------------------
22−// Initialize services
23−// ---------------------------------------------------------------------------
24−
25−const db = await getDb();
26−const authHandlers = createAuthHandlers(db);
27−const teamHandlers = createTeamHandlers(db);
28−const apiHandler = createCloudApiHandler(db, ENCRYPTION_KEY);
29−
30−// ---------------------------------------------------------------------------
31−// Static file serving (frontend)
32−// ---------------------------------------------------------------------------
33−
34−const WEB_DIST_DIR = resolve(import.meta.dirname, "../dist");
35−
36−const serveStatic = async (pathname: string): Promise<Response | null> => {
37− const key = pathname.replace(/^\//, "");
38− const filePath = resolve(WEB_DIST_DIR, key);
39− if (!filePath.startsWith(WEB_DIST_DIR)) return null;
40−
41− const file = Bun.file(filePath);
42− if (await file.exists()) {
43− return new Response(file, {
44− headers: { "content-type": file.type || "application/octet-stream" },
45− });
46− }
47−
48− // SPA fallback
49− const index = Bun.file(resolve(WEB_DIST_DIR, "index.html"));
50− if (await index.exists()) {
51− return new Response(index, { headers: { "content-type": "text/html" } });
52− }
53−
54− return null;
55−};
56−
57−// ---------------------------------------------------------------------------
58−// Main server
59−// ---------------------------------------------------------------------------
60−
61−const server = Bun.serve({
62− port: PORT,
63− fetch: async (request: Request): Promise<Response> => {
64− const url = new URL(request.url);
65−
66− // --- Auth routes (public) ---
67− if (url.pathname === "/auth/login") return authHandlers.login(request);
68− if (url.pathname === "/auth/callback") return authHandlers.callback(request);
69− if (url.pathname === "/auth/logout") return authHandlers.logout(request);
70− if (url.pathname === "/auth/me") return authHandlers.me(request);
71−
72− // --- Team routes (authenticated) ---
73− if (url.pathname === "/api/team/members" && request.method === "GET")
74− return teamHandlers.listMembers(request);
75− if (url.pathname === "/api/team/members" && request.method === "DELETE")
76− return teamHandlers.removeMember(request);
77− if (url.pathname === "/api/team/invite" && request.method === "POST")
78− return teamHandlers.invite(request);
79− if (url.pathname === "/api/team/invitations" && request.method === "GET")
80− return teamHandlers.listInvitations(request);
81−
82− // --- Effect HTTP API (authenticated) ---
83− if (
84− url.pathname.startsWith("/v1/") ||
85− url.pathname.startsWith("/docs") ||
86− url.pathname === "/openapi.json"
87− ) {
88− return apiHandler(request);
89− }
90−
91− // --- Static frontend ---
92− const staticResponse = await serveStatic(url.pathname);
93− if (staticResponse) return staticResponse;
94−
95− return new Response("Not Found", { status: 404 });
96− },
97−});
98−
99−console.log(`Executor Cloud running on http://localhost:${server.port}`);
apps/cloud/src/routeTree.gen.ts+198−0
@@ -0,0 +1,198 @@
1+/* eslint-disable */
2+
3+// @ts-nocheck
4+
5+// noinspection JSUnusedGlobalSymbols
6+
7+// This file was automatically generated by TanStack Router.
8+// You should NOT make any changes in this file as it will be overwritten.
9+// Additionally, you should also exclude this file from your linter and/or formatter to prevent it from being checked or modified.
10+
11+import { Route as rootRouteImport } from './routes/__root'
12+import { Route as ToolsRouteImport } from './routes/tools'
13+import { Route as SecretsRouteImport } from './routes/secrets'
14+import { Route as IndexRouteImport } from './routes/index'
15+import { Route as V1SplatRouteImport } from './routes/v1.$'
16+import { Route as SourcesNamespaceRouteImport } from './routes/sources.$namespace'
17+import { Route as AuthSplatRouteImport } from './routes/auth.$'
18+import { Route as SourcesAddPluginKeyRouteImport } from './routes/sources.add.$pluginKey'
19+
20+const ToolsRoute = ToolsRouteImport.update({
21+ id: '/tools',
22+ path: '/tools',
23+ getParentRoute: () => rootRouteImport,
24+} as any)
25+const SecretsRoute = SecretsRouteImport.update({
26+ id: '/secrets',
27+ path: '/secrets',
28+ getParentRoute: () => rootRouteImport,
29+} as any)
30+const IndexRoute = IndexRouteImport.update({
31+ id: '/',
32+ path: '/',
33+ getParentRoute: () => rootRouteImport,
34+} as any)
35+const V1SplatRoute = V1SplatRouteImport.update({
36+ id: '/v1/$',
37+ path: '/v1/$',
38+ getParentRoute: () => rootRouteImport,
39+} as any)
40+const SourcesNamespaceRoute = SourcesNamespaceRouteImport.update({
41+ id: '/sources/$namespace',
42+ path: '/sources/$namespace',
43+ getParentRoute: () => rootRouteImport,
44+} as any)
45+const AuthSplatRoute = AuthSplatRouteImport.update({
46+ id: '/auth/$',
47+ path: '/auth/$',
48+ getParentRoute: () => rootRouteImport,
49+} as any)
50+const SourcesAddPluginKeyRoute = SourcesAddPluginKeyRouteImport.update({
51+ id: '/sources/add/$pluginKey',
52+ path: '/sources/add/$pluginKey',
53+ getParentRoute: () => rootRouteImport,
54+} as any)
55+
56+export interface FileRoutesByFullPath {
57+ '/': typeof IndexRoute
58+ '/secrets': typeof SecretsRoute
59+ '/tools': typeof ToolsRoute
60+ '/auth/$': typeof AuthSplatRoute
61+ '/sources/$namespace': typeof SourcesNamespaceRoute
62+ '/v1/$': typeof V1SplatRoute
63+ '/sources/add/$pluginKey': typeof SourcesAddPluginKeyRoute
64+}
65+export interface FileRoutesByTo {
66+ '/': typeof IndexRoute
67+ '/secrets': typeof SecretsRoute
68+ '/tools': typeof ToolsRoute
69+ '/auth/$': typeof AuthSplatRoute
70+ '/sources/$namespace': typeof SourcesNamespaceRoute
71+ '/v1/$': typeof V1SplatRoute
72+ '/sources/add/$pluginKey': typeof SourcesAddPluginKeyRoute
73+}
74+export interface FileRoutesById {
75+ __root__: typeof rootRouteImport
76+ '/': typeof IndexRoute
77+ '/secrets': typeof SecretsRoute
78+ '/tools': typeof ToolsRoute
79+ '/auth/$': typeof AuthSplatRoute
80+ '/sources/$namespace': typeof SourcesNamespaceRoute
81+ '/v1/$': typeof V1SplatRoute
82+ '/sources/add/$pluginKey': typeof SourcesAddPluginKeyRoute
83+}
84+export interface FileRouteTypes {
85+ fileRoutesByFullPath: FileRoutesByFullPath
86+ fullPaths:
87+ | '/'
88+ | '/secrets'
89+ | '/tools'
90+ | '/auth/$'
91+ | '/sources/$namespace'
92+ | '/v1/$'
93+ | '/sources/add/$pluginKey'
94+ fileRoutesByTo: FileRoutesByTo
95+ to:
96+ | '/'
97+ | '/secrets'
98+ | '/tools'
99+ | '/auth/$'
100+ | '/sources/$namespace'
101+ | '/v1/$'
102+ | '/sources/add/$pluginKey'
103+ id:
104+ | '__root__'
105+ | '/'
106+ | '/secrets'
107+ | '/tools'
108+ | '/auth/$'
109+ | '/sources/$namespace'
110+ | '/v1/$'
111+ | '/sources/add/$pluginKey'
112+ fileRoutesById: FileRoutesById
113+}
114+export interface RootRouteChildren {
115+ IndexRoute: typeof IndexRoute
116+ SecretsRoute: typeof SecretsRoute
117+ ToolsRoute: typeof ToolsRoute
118+ AuthSplatRoute: typeof AuthSplatRoute
119+ SourcesNamespaceRoute: typeof SourcesNamespaceRoute
120+ V1SplatRoute: typeof V1SplatRoute
121+ SourcesAddPluginKeyRoute: typeof SourcesAddPluginKeyRoute
122+}
123+
124+declare module '@tanstack/react-router' {
125+ interface FileRoutesByPath {
126+ '/tools': {
127+ id: '/tools'
128+ path: '/tools'
129+ fullPath: '/tools'
130+ preLoaderRoute: typeof ToolsRouteImport
131+ parentRoute: typeof rootRouteImport
132+ }
133+ '/secrets': {
134+ id: '/secrets'
135+ path: '/secrets'
136+ fullPath: '/secrets'
137+ preLoaderRoute: typeof SecretsRouteImport
138+ parentRoute: typeof rootRouteImport
139+ }
140+ '/': {
141+ id: '/'
142+ path: '/'
143+ fullPath: '/'
144+ preLoaderRoute: typeof IndexRouteImport
145+ parentRoute: typeof rootRouteImport
146+ }
147+ '/v1/$': {
148+ id: '/v1/$'
149+ path: '/v1/$'
150+ fullPath: '/v1/$'
151+ preLoaderRoute: typeof V1SplatRouteImport
152+ parentRoute: typeof rootRouteImport
153+ }
154+ '/sources/$namespace': {
155+ id: '/sources/$namespace'
156+ path: '/sources/$namespace'
157+ fullPath: '/sources/$namespace'
158+ preLoaderRoute: typeof SourcesNamespaceRouteImport
159+ parentRoute: typeof rootRouteImport
160+ }
161+ '/auth/$': {
162+ id: '/auth/$'
163+ path: '/auth/$'
164+ fullPath: '/auth/$'
165+ preLoaderRoute: typeof AuthSplatRouteImport
166+ parentRoute: typeof rootRouteImport
167+ }
168+ '/sources/add/$pluginKey': {
169+ id: '/sources/add/$pluginKey'
170+ path: '/sources/add/$pluginKey'
171+ fullPath: '/sources/add/$pluginKey'
172+ preLoaderRoute: typeof SourcesAddPluginKeyRouteImport
173+ parentRoute: typeof rootRouteImport
174+ }
175+ }
176+}
177+
178+const rootRouteChildren: RootRouteChildren = {
179+ IndexRoute: IndexRoute,
180+ SecretsRoute: SecretsRoute,
181+ ToolsRoute: ToolsRoute,
182+ AuthSplatRoute: AuthSplatRoute,
183+ SourcesNamespaceRoute: SourcesNamespaceRoute,
184+ V1SplatRoute: V1SplatRoute,
185+ SourcesAddPluginKeyRoute: SourcesAddPluginKeyRoute,
186+}
187+export const routeTree = rootRouteImport
188+ ._addFileChildren(rootRouteChildren)
189+ ._addFileTypes<FileRouteTypes>()
190+
191+import type { getRouter } from './router.tsx'
192+import type { createStart } from '@tanstack/react-start'
193+declare module '@tanstack/react-start' {
194+ interface Register {
195+ ssr: true
196+ router: Awaited<ReturnType<typeof getRouter>>
197+ }
198+}
apps/cloud/src/router.tsx+10−0
@@ -0,0 +1,10 @@
1+import { createRouter } from "@tanstack/react-router";
2+import { routeTree } from "./routeTree.gen";
3+
4+export const getRouter = () => {
5+ return createRouter({
6+ routeTree,
7+ scrollRestoration: true,
8+ defaultPreloadStaleTime: 0,
9+ });
10+};
apps/cloud/src/routes/__root.tsx+69−0
@@ -0,0 +1,69 @@
1+import React from "react";
2+import { HeadContent, Outlet, Scripts, createRootRoute } from "@tanstack/react-router";
3+import { ExecutorProvider } from "@executor/react/api/provider";
4+import { AuthProvider, useAuth } from "../web/auth";
5+import { LoginPage } from "../web/pages/login";
6+import { Shell } from "../web/shell";
7+import appCss from "@executor/react/globals.css?url";
8+
9+export const Route = createRootRoute({
10+ head: () => ({
11+ meta: [
12+ { charSet: "utf-8" },
13+ { name: "viewport", content: "width=device-width, initial-scale=1" },
14+ { title: "Executor Cloud" },
15+ ],
16+ links: [
17+ { rel: "preconnect", href: "https://fonts.googleapis.com" },
18+ { rel: "preconnect", href: "https://fonts.gstatic.com", crossOrigin: "anonymous" },
19+ { rel: "stylesheet", href: "https://fonts.googleapis.com/css2?family=DM+Sans:ital,opsz,wght@0,9..40,300..700;1,9..40,300..700&family=Instrument+Serif&family=JetBrains+Mono:wght@400;500&display=swap" },
20+ { rel: "stylesheet", href: appCss },
21+ ],
22+ }),
23+ component: RootComponent,
24+ shellComponent: RootDocument,
25+});
26+
27+function RootDocument({ children }: { children: React.ReactNode }) {
28+ return (
29+ <html lang="en">
30+ <head>
31+ <HeadContent />
32+ </head>
33+ <body>
34+ {children}
35+ <Scripts />
36+ </body>
37+ </html>
38+ );
39+}
40+
41+function RootComponent() {
42+ return (
43+ <AuthProvider>
44+ <AuthGate />
45+ </AuthProvider>
46+ );
47+}
48+
49+function AuthGate() {
50+ const auth = useAuth();
51+
52+ if (auth.status === "loading") {
53+ return (
54+ <div className="flex min-h-screen items-center justify-center bg-background">
55+ <p className="text-sm text-muted-foreground">Loading...</p>
56+ </div>
57+ );
58+ }
59+
60+ if (auth.status === "unauthenticated") {
61+ return <LoginPage />;
62+ }
63+
64+ return (
65+ <ExecutorProvider>
66+ <Shell />
67+ </ExecutorProvider>
68+ );
69+}
apps/cloud/src/routes/index.tsx+6−0
@@ -0,0 +1,6 @@
1+import { createFileRoute } from "@tanstack/react-router";
2+import { SourcesPage } from "@executor/react/pages/sources";
3+
4+export const Route = createFileRoute("/")({
5+ component: SourcesPage,
6+});
apps/cloud/src/routes/secrets.tsx+6−0
@@ -0,0 +1,6 @@
1+import { createFileRoute } from "@tanstack/react-router";
2+import { SecretsPage } from "@executor/react/pages/secrets";
3+
4+export const Route = createFileRoute("/secrets")({
5+ component: SecretsPage,
6+});
apps/cloud/src/routes/sources.$namespace.tsx+9−0
@@ -0,0 +1,9 @@
1+import { createFileRoute } from "@tanstack/react-router";
2+import { SourceDetailPage } from "@executor/react/pages/source-detail";
3+
4+export const Route = createFileRoute("/sources/$namespace")({
5+ component: () => {
6+ const { namespace } = Route.useParams();
7+ return <SourceDetailPage namespace={namespace} />;
8+ },
9+});
apps/cloud/src/routes/sources.add.$pluginKey.tsx+19−0
@@ -0,0 +1,19 @@
1+import { Schema } from "effect";
2+import { createFileRoute } from "@tanstack/react-router";
3+import { SourcesAddPage } from "@executor/react/pages/sources-add";
4+
5+const SearchParams = Schema.standardSchemaV1(
6+ Schema.Struct({
7+ url: Schema.optional(Schema.String),
8+ preset: Schema.optional(Schema.String),
9+ }),
10+);
11+
12+export const Route = createFileRoute("/sources/add/$pluginKey")({
13+ validateSearch: SearchParams,
14+ component: () => {
15+ const { pluginKey } = Route.useParams();
16+ const { url, preset } = Route.useSearch();
17+ return <SourcesAddPage pluginKey={pluginKey} url={url} preset={preset} />;
18+ },
19+});
apps/cloud/src/routes/tools.tsx+6−0
@@ -0,0 +1,6 @@
1+import { createFileRoute } from "@tanstack/react-router";
2+import { ToolsPage } from "@executor/react/pages/tools";
3+
4+export const Route = createFileRoute("/tools")({
5+ component: ToolsPage,
6+});
apps/cloud/src/routes/v1.$.ts+14−0
@@ -0,0 +1,14 @@
1+import { createFileRoute } from "@tanstack/react-router";
2+import { handleApiRequest } from "../server/api-handler";
3+
4+export const Route = createFileRoute("/v1/$")({
5+ server: {
6+ handlers: {
7+ GET: ({ request }) => handleApiRequest(request),
8+ POST: ({ request }) => handleApiRequest(request),
9+ PUT: ({ request }) => handleApiRequest(request),
10+ DELETE: ({ request }) => handleApiRequest(request),
11+ PATCH: ({ request }) => handleApiRequest(request),
12+ },
13+ },
14+});
apps/cloud/src/server/api-handler.ts+9−0
@@ -0,0 +1,9 @@
1+import { createCloudApiHandler } from "../api";
2+import { getDb } from "../services/db";
3+
4+const handlerPromise = getDb().then((db) =>
5+ createCloudApiHandler(db, process.env.ENCRYPTION_KEY ?? "local-dev-encryption-key"),
6+);
7+
8+export const handleApiRequest = async (request: Request) =>
9+ (await handlerPromise)(request);
apps/cloud/src/vite-env.d.ts+1−0
@@ -0,0 +1 @@
1+/// <reference types="vite/client" />
apps/cloud/src/web/App.tsx+0−29
@@ -1,29 +0,0 @@
1−import React from "react";
2−import { RouterProvider } from "@tanstack/react-router";
3−import { AuthProvider, useAuth } from "./auth";
4−import { LoginPage } from "./pages/login";
5−import { router } from "./router";
6−
7−const AuthGate = () => {
8− const auth = useAuth();
9−
10− if (auth.status === "loading") {
11− return (
12− <div className="flex min-h-screen items-center justify-center bg-background">
13− <p className="text-sm text-muted-foreground">Loading...</p>
14− </div>
15− );
16− }
17−
18− if (auth.status === "unauthenticated") {
19− return <LoginPage />;
20− }
21−
22− return <RouterProvider router={router} />;
23−};
24−
25−export const App = () => (
26− <AuthProvider>
27− <AuthGate />
28− </AuthProvider>
29−);
apps/cloud/src/web/main.tsx+0−7
@@ -1,7 +0,0 @@
1−import React from "react";
2−import { createRoot } from "react-dom/client";
3−import "@executor/react/globals.css";
4−import { App } from "./App";
5−
6−const root = createRoot(document.getElementById("root")!);
7−root.render(<App />);
apps/cloud/src/web/router.tsx+0−93
@@ -1,93 +0,0 @@
1−import {
2− createRouter,
3− createRootRoute,
4− createRoute,
5−} from "@tanstack/react-router";
6−import { ExecutorProvider } from "@executor/react/api/provider";
7−import { ToolsPage } from "@executor/react/pages/tools";
8−import { SourcesPage } from "@executor/react/pages/sources";
9−import { SourcesAddPage } from "@executor/react/pages/sources-add";
10−import { SourceDetailPage } from "@executor/react/pages/source-detail";
11−import { SecretsPage } from "@executor/react/pages/secrets";
12−import { Shell } from "./shell";
13−
14−// ---------------------------------------------------------------------------
15−// Root layout — Shell renders <Outlet /> directly
16−// ---------------------------------------------------------------------------
17−
18−const rootRoute = createRootRoute({
19− component: () => (
20− <ExecutorProvider>
21− <Shell />
22− </ExecutorProvider>
23− ),
24−});
25−
26−// ---------------------------------------------------------------------------
27−// Routes — same as apps/web
28−// ---------------------------------------------------------------------------
29−
30−const indexRoute = createRoute({
31− getParentRoute: () => rootRoute,
32− path: "/",
33− component: SourcesPage,
34−});
35−
36−const toolsRoute = createRoute({
37− getParentRoute: () => rootRoute,
38− path: "/tools",
39− component: ToolsPage,
40−});
41−
42−const sourcesAddRoute = createRoute({
43− getParentRoute: () => rootRoute,
44− path: "/sources/add/$pluginKey",
45− validateSearch: (
46− search: Record<string, unknown>,
47− ): { url?: string; preset?: string } => ({
48− url: typeof search.url === "string" ? search.url : undefined,
49− preset: typeof search.preset === "string" ? search.preset : undefined,
50− }),
51− component: () => {
52− const { pluginKey } = sourcesAddRoute.useParams();
53− const { url, preset } = sourcesAddRoute.useSearch();
54− return (
55− <SourcesAddPage pluginKey={pluginKey} url={url} preset={preset} />
56− );
57− },
58−});
59−
60−const sourceDetailRoute = createRoute({
61− getParentRoute: () => rootRoute,
62− path: "/sources/$namespace",
63− component: () => {
64− const { namespace } = sourceDetailRoute.useParams();
65− return <SourceDetailPage namespace={namespace} />;
66− },
67−});
68−
69−const secretsRoute = createRoute({
70− getParentRoute: () => rootRoute,
71− path: "/secrets",
72− component: SecretsPage,
73−});
74−
75−// ---------------------------------------------------------------------------
76−// Router
77−// ---------------------------------------------------------------------------
78−
79−const routeTree = rootRoute.addChildren([
80− indexRoute,
81− toolsRoute,
82− sourcesAddRoute,
83− sourceDetailRoute,
84− secretsRoute,
85−]);
86−
87−export const router = createRouter({ routeTree });
88−
89−declare module "@tanstack/react-router" {
90− interface Register {
91− router: typeof router;
92− }
93−}
apps/cloud/src/web/shell.tsx+14−227
@@ -1,169 +1,11 @@
11 import { Link, Outlet, useLocation } from "@tanstack/react-router";
2−import { useCallback, useEffect, useRef, useState } from "react";
2+import { useEffect, useRef, useState } from "react";
33 import { useAtomRefresh, useAtomValue, Result } from "@effect-atom/atom-react";
44 import { sourcesAtom, toolsAtom } from "@executor/react/api/atoms";
5−import { useScope, useScopeInfo } from "@executor/react/api/scope-context";
5+import { useScope } from "@executor/react/api/scope-context";
66 import { Button } from "@executor/react/components/button";
77 import { useAuth } from "./auth";
88
9−// ── Env ─────────────────────────────────────────────────────────────────
10−
11−type AppMetaEnv = {
12− readonly VITE_APP_VERSION: string;
13− readonly VITE_GITHUB_URL: string;
14−};
15−
16−const { VITE_APP_VERSION, VITE_GITHUB_URL } = (import.meta as ImportMeta & {
17− readonly env: AppMetaEnv;
18−}).env;
19−
20−// ── Version helpers ─────────────────────────────────────────────────────
21−
22−type UpdateChannel = "latest" | "beta";
23−
24−const EXECUTOR_DIST_TAGS_PATH = "/v1/app/npm/dist-tags";
25−
26−type ParsedVersion = {
27− readonly major: number;
28− readonly minor: number;
29− readonly patch: number;
30− readonly prerelease: ReadonlyArray<string | number> | null;
31−};
32−
33−const semverPattern =
34− /^(?<major>\d+)\.(?<minor>\d+)\.(?<patch>\d+)(?:-(?<prerelease>[0-9A-Za-z.-]+))?(?:\+[0-9A-Za-z.-]+)?$/;
35−
36−const resolveUpdateChannel = (version: string): UpdateChannel =>
37− version.includes("-beta.") ? "beta" : "latest";
38−
39−const parseVersion = (version: string): ParsedVersion | null => {
40− const match = version.trim().match(semverPattern);
41− if (!match?.groups) return null;
42− return {
43− major: Number(match.groups.major),
44− minor: Number(match.groups.minor),
45− patch: Number(match.groups.patch),
46− prerelease: match.groups.prerelease
47− ? match.groups.prerelease.split(".").map((id) =>
48− /^\d+$/.test(id) ? Number(id) : id,
49− )
50− : null,
51− };
52−};
53−
54−const comparePrereleaseIdentifiers = (
55− left: ReadonlyArray<string | number> | null,
56− right: ReadonlyArray<string | number> | null,
57−): number => {
58− if (left === null && right === null) return 0;
59− if (left === null) return 1;
60− if (right === null) return -1;
61− const max = Math.max(left.length, right.length);
62− for (let i = 0; i < max; i++) {
63− const l = left[i];
64− const r = right[i];
65− if (l === undefined) return -1;
66− if (r === undefined) return 1;
67− if (l === r) continue;
68− if (typeof l === "number" && typeof r === "number") return l < r ? -1 : 1;
69− if (typeof l === "number") return -1;
70− if (typeof r === "number") return 1;
71− return l < r ? -1 : 1;
72− }
73− return 0;
74−};
75−
76−const compareVersions = (left: string, right: string): number | null => {
77− const lv = parseVersion(left);
78− const rv = parseVersion(right);
79− if (!lv || !rv) return null;
80− if (lv.major !== rv.major) return lv.major < rv.major ? -1 : 1;
81− if (lv.minor !== rv.minor) return lv.minor < rv.minor ? -1 : 1;
82− if (lv.patch !== rv.patch) return lv.patch < rv.patch ? -1 : 1;
83− return comparePrereleaseIdentifiers(lv.prerelease, rv.prerelease);
84−};
85−
86−// ── useLatestVersion ────────────────────────────────────────────────────
87−
88−function useLatestVersion(currentVersion: string) {
89− const channel = resolveUpdateChannel(currentVersion);
90− const [latestVersion, setLatestVersion] = useState<string | null>(null);
91−
92− useEffect(() => {
93− let cancelled = false;
94− fetch(EXECUTOR_DIST_TAGS_PATH)
95− .then(async (res) => {
96− if (!res.ok) throw new Error(`Failed to load dist tags: ${res.status}`);
97− return res.json() as Promise<Partial<Record<UpdateChannel, string>>>;
98− })
99− .then((data) => {
100− if (!cancelled) setLatestVersion(data[channel] ?? null);
101− })
102− .catch(() => {});
103− return () => { cancelled = true; };
104− }, [channel]);
105−
106− const updateAvailable =
107− latestVersion !== null && compareVersions(currentVersion, latestVersion) === -1;
108−
109− return { latestVersion, updateAvailable, channel };
110−}
111−
112−// ── UpdateCard ──────────────────────────────────────────────────────────
113−
114−function UpdateCard(props: { latestVersion: string; channel: UpdateChannel }) {
115− const command = `npm i -g executor@${props.channel}`;
116− const [copied, setCopied] = useState(false);
117−
118− const handleCopy = useCallback(() => {
119− void navigator.clipboard.writeText(command).then(() => {
120− setCopied(true);
121− setTimeout(() => setCopied(false), 1500);
122− });
123− }, [command]);
124−
125− return (
126− <div className="mx-2 mb-2 rounded-xl border border-primary/25 bg-primary/[0.06] p-3">
127− <div className="flex items-center gap-2">
128− <div className="flex size-5 shrink-0 items-center justify-center rounded-full bg-primary/15">
129− <svg viewBox="0 0 16 16" fill="none" className="size-3 text-primary">
130− <path d="M8 3v7M5 7l3 3 3-3" stroke="currentColor" strokeWidth="1.4" strokeLinecap="round" strokeLinejoin="round" />
131− <path d="M3 12h10" stroke="currentColor" strokeWidth="1.4" strokeLinecap="round" />
132− </svg>
133− </div>
134− <div className="min-w-0">
135− <p className="text-[11px] font-semibold text-foreground">Update available</p>
136− <p className="text-[10px] text-muted-foreground">
137− v{props.latestVersion}
138− </p>
139− </div>
140− </div>
141− <Button
142− type="button"
143− variant="outline"
144− onClick={handleCopy}
145− className="mt-2.5 flex w-full items-center justify-between gap-2 rounded-lg border-border/60 bg-background/50 px-2.5 py-1.5 text-left hover:bg-background/80"
146− >
147− <code className="truncate font-mono text-[10px] text-sidebar-foreground">
148− {command}
149− </code>
150− <span className="shrink-0 text-muted-foreground transition-colors group-hover:text-foreground">
151− {copied ? (
152− <svg viewBox="0 0 16 16" fill="none" className="size-3 text-primary">
153− <path d="M3 8.5l3.5 3.5L13 4" stroke="currentColor" strokeWidth="1.4" strokeLinecap="round" strokeLinejoin="round" />
154− </svg>
155− ) : (
156− <svg viewBox="0 0 16 16" fill="none" className="size-3">
157− <rect x="5" y="5" width="8" height="8" rx="1.5" stroke="currentColor" strokeWidth="1.2" />
158− <path d="M3 11V3.5A.5.5 0 013.5 3H11" stroke="currentColor" strokeWidth="1.2" strokeLinecap="round" />
159− </svg>
160− )}
161− </span>
162− </Button>
163− </div>
164− );
165−}
166−
1679 // ── NavItem ──────────────────────────────────────────────────────────────
16810
16911 function NavItem(props: { to: string; label: string; active: boolean; onNavigate?: () => void }) {
@@ -233,30 +75,6 @@ function SourceList(props: { pathname: string; onNavigate?: () => void }) { · 63 unmodified lines
23375 });
23476 }
23577
236−// ── ScopeLabel ───────────────────────────────────────────────────────────
237−
238−function ScopeLabel() {
239− const { name } = useScopeInfo();
240− // Show just the last folder name, with full path as tooltip
241− const parts = name.replace(/\/+$/, "").split("/");
242− const folder = parts[parts.length - 1] || name;
243−
244− return (
245− <div className="mb-1.5 flex items-center gap-1.5 rounded-md px-2.5 py-1.5" title={name}>
246− <svg viewBox="0 0 16 16" fill="none" className="size-3.5 shrink-0 text-muted-foreground/50">
247− <path
248− d="M2 4.5C2 3.67 2.67 3 3.5 3h3.09a1 1 0 0 1 .7.29l1.42 1.42a1 1 0 0 0 .7.29H12.5c.83 0 1.5.67 1.5 1.5v5.5c0 .83-.67 1.5-1.5 1.5h-9A1.5 1.5 0 0 1 2 12V4.5z"
249− stroke="currentColor"
250− strokeWidth="1.2"
251− />
252− </svg>
253− <span className="truncate text-[12px] font-medium text-foreground/80">
254− {folder}
255− </span>
256− </div>
257− );
258−}
259−
26078 // ── UserFooter ──────────────────────────────────────────────────────────
26179
26280 function UserFooter() {
@@ -291,15 +109,17 @@ function UserFooter() { · 28 unmodified lines
291109 </p>
292110 )}
293111 </div>
294− <a
295− href="/auth/logout"
296− className="shrink-0 rounded-md p-1 text-muted-foreground/50 transition-colors hover:bg-sidebar-active hover:text-foreground"
297− title="Sign out"
298− >
299− <svg viewBox="0 0 16 16" fill="none" className="size-3.5">
300− <path d="M6 2H3.5A1.5 1.5 0 002 3.5v9A1.5 1.5 0 003.5 14H6M10.5 11.5L14 8l-3.5-3.5M14 8H6" stroke="currentColor" strokeWidth="1.2" strokeLinecap="round" strokeLinejoin="round" />
301− </svg>
302− </a>
112+ <form action="/auth/logout" method="post">
113+ <button
114+ type="submit"
115+ className="shrink-0 rounded-md p-1 text-muted-foreground/50 transition-colors hover:bg-sidebar-active hover:text-foreground"
116+ title="Sign out"
117+ >
118+ <svg viewBox="0 0 16 16" fill="none" className="size-3.5">
119+ <path d="M6 2H3.5A1.5 1.5 0 002 3.5v9A1.5 1.5 0 003.5 14H6M10.5 11.5L14 8l-3.5-3.5M14 8H6" stroke="currentColor" strokeWidth="1.2" strokeLinecap="round" strokeLinejoin="round" />
120+ </svg>
121+ </button>
122+ </form>
303123 </div>
304124 </div>
305125 );
@@ -311,9 +131,6 @@ function SidebarContent(props: { · 5 unmodified lines
311131 pathname: string;
312132 onNavigate?: () => void;
313133 showBrand?: boolean;
314− updateAvailable: boolean;
315− latestVersion: string | null;
316− channel: UpdateChannel;
317134 }) {
318135 const isHome = props.pathname === "/";
319136 const isSecrets = props.pathname === "/secrets";
@@ -331,7 +148,6 @@ function SidebarContent(props: { · 11 unmodified lines
331148 )}
332149
333150 <nav className="flex flex-1 flex-col overflow-y-auto p-2">
334− <ScopeLabel />
335151 <NavItem
336152 to="/"
337153 label="Sources"
@@ -345,7 +161,6 @@ function SidebarContent(props: { · 7 unmodified lines
345161 onNavigate={props.onNavigate}
346162 />
347163
348− {/* Sources list */}
349164 <div className="mt-5 mb-1 px-2.5 text-[10px] font-medium uppercase tracking-widest text-muted-foreground/50">
350165 <span>Configured</span>
351166 </div>
@@ -353,7 +168,6 @@ function SidebarContent(props: { · 1 unmodified line
353168 <SourceList pathname={props.pathname} onNavigate={props.onNavigate} />
354169 </nav>
355170
356− {/* User */}
357171 <UserFooter />
358172 </>
359173 );
@@ -367,7 +181,6 @@ export function Shell() { · 7 unmodified lines
367181 const scopeId = useScope();
368182 const refreshSources = useAtomRefresh(sourcesAtom(scopeId));
369183 const refreshTools = useAtomRefresh(toolsAtom(scopeId));
370− const { latestVersion, updateAvailable, channel } = useLatestVersion(VITE_APP_VERSION);
371184 const lastPathname = useRef(pathname);
372185 const [mobileSidebarOpen, setMobileSidebarOpen] = useState(false);
373186 if (lastPathname.current !== pathname) {
@@ -385,33 +198,11 @@ export function Shell() { · 11 unmodified lines
385198 };
386199 }, [mobileSidebarOpen]);
387200
388− useEffect(() => {
389− if (!import.meta.hot) {
390− return;
391− }
392−
393− const refreshBackendData = () => {
394− refreshSources();
395− refreshTools();
396− };
397−
398− import.meta.hot.on("executor:backend-updated", refreshBackendData);
399−
400− return () => {
401− import.meta.hot?.off("executor:backend-updated", refreshBackendData);
402− };
403− }, [refreshSources, refreshTools]);
404−
405201 return (
406202 <div className="flex h-screen overflow-hidden">
407203 {/* Desktop sidebar */}
408204 <aside className="hidden w-52 shrink-0 border-r border-sidebar-border bg-sidebar md:flex md:flex-col lg:w-56">
409− <SidebarContent
410− pathname={pathname}
411− updateAvailable={updateAvailable}
412− latestVersion={latestVersion}
413− channel={channel}
414− />
205+ <SidebarContent pathname={pathname} />
415206 </aside>
416207
417208 {/* Mobile sidebar overlay */}
@@ -445,9 +236,6 @@ export function Shell() { · 27 unmodified lines
445236 pathname={pathname}
446237 onNavigate={() => setMobileSidebarOpen(false)}
447238 showBrand={false}
448− updateAvailable={updateAvailable}
449− latestVersion={latestVersion}
450− channel={channel}
451239 />
452240 </div>
453241 </div>
@@ -475,7 +263,6 @@ export function Shell() { · 21 unmodified lines
475263 <div className="w-8 shrink-0" />
476264 </div>
477265
478− {/* Outlet — pages control their own padding/scroll */}
479266 <Outlet />
480267 </main>
481268 </div>
apps/cloud/tsconfig.json+2−2
@@ -7,7 +7,7 @@ · 6 unmodified lines
77 "esModuleInterop": true,
88 "skipLibCheck": true,
99 "outDir": "dist",
10− "rootDir": "src",
10+ "rootDir": ".",
1111 "declaration": true,
1212 "declarationMap": true,
1313 "sourceMap": true,
@@ -19,5 +19,5 @@ · 5 unmodified lines
1919 }
2020 ]
2121 },
22− "include": ["src"]
22+ "include": ["src", "vite.config.ts"]
2323 }
apps/cloud/vite.config.ts+11−14
@@ -1,22 +1,19 @@
11 import { defineConfig } from "vite";
2+import { tanstackStart } from "@tanstack/react-start/plugin/vite";
23 import react from "@vitejs/plugin-react";
34 import tailwindcss from "@tailwindcss/vite";
45
5−const API_PORT = process.env.API_PORT ?? "3001";
6−
76 export default defineConfig({
8− plugins: [react(), tailwindcss()],
9− define: {
10− "import.meta.env.VITE_APP_VERSION": JSON.stringify("0.0.0"),
11− "import.meta.env.VITE_GITHUB_URL": JSON.stringify("https://github.com/RhysSullivan/executor"),
12− },
137 server: {
14− proxy: {
15− "/v1": `http://localhost:${API_PORT}`,
16− "/auth": `http://localhost:${API_PORT}`,
17− "/api": `http://localhost:${API_PORT}`,
18− "/docs": `http://localhost:${API_PORT}`,
19− "/openapi.json": `http://localhost:${API_PORT}`,
20− },
8+ port: parseInt(process.env.PORT ?? "5173", 10),
9+ host: "127.0.0.1",
2110 },
11+ resolve: { tsconfigPaths: true },
12+ plugins: [
13+ tailwindcss(),
14+ tanstackStart({
15+ spa: { enabled: true },
16+ }),
17+ react(),
18+ ],
2219 });
apps/desktop/package.json+1−1
@@ -24,7 +24,7 @@ · 23 unmodified lines
2424 "@types/node": "catalog:",
2525 "electron": "35.7.5",
2626 "electron-builder": "^26.0.12",
27− "typescript": "^5.9.3"
27+ "typescript": "catalog:"
2828 },
2929 "build": {
3030 "appId": "com.executor.desktop",
apps/local/index.html+0−15
@@ -1,15 +0,0 @@
1−<!doctype html>
2−<html lang="en">
3− <head>
4− <meta charset="UTF-8" />
5− <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6− <title>Executor</title>
7− <link rel="preconnect" href="https://fonts.googleapis.com" />
8− <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
9− <link href="https://fonts.googleapis.com/css2?family=DM+Sans:ital,opsz,wght@0,9..40,300..700;1,9..40,300..700&family=Instrument+Serif&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet" />
10− </head>
11− <body>
12− <div id="root"></div>
13− <script type="module" src="/src/web/main.tsx"></script>
14− </body>
15−</html>
apps/local/package.json+12−11
@@ -28,26 +28,27 @@ · 27 unmodified lines
2828 "@modelcontextprotocol/sdk": "^1.12.1",
2929 "@shikijs/langs": "^4.0.2",
3030 "@shikijs/themes": "^4.0.2",
31− "@tanstack/react-router": "^1.168.10",
31+ "@tanstack/react-router": "catalog:",
32+ "@tanstack/react-start": "catalog:",
3233 "effect": "catalog:",
33− "react": "^19.1.0",
34− "react-dom": "^19.1.0",
34+ "react": "catalog:",
35+ "react-dom": "catalog:",
3536 "shiki": "^4.0.2",
3637 "streamdown": "^2.5.0",
37− "tailwindcss": "^4.1.10"
38+ "tailwindcss": "catalog:"
3839 },
3940 "devDependencies": {
40− "@tailwindcss/vite": "^4.1.10",
41+ "@tailwindcss/vite": "catalog:",
4142 "@types/node": "catalog:",
42− "@types/react": "^19.1.0",
43− "@types/react-dom": "^19.1.0",
44− "@vitejs/plugin-react": "^4.5.2",
43+ "@types/react": "catalog:",
44+ "@types/react-dom": "catalog:",
45+ "@vitejs/plugin-react": "catalog:",
4546 "bun-types": "catalog:",
46− "typescript": "^5.9.3",
47− "vite": "^6.3.5"
47+ "typescript": "catalog:",
48+ "vite": "catalog:"
4849 },
4950 "scripts": {
50− "dev": "bunx --bun vite",
51+ "dev": "bunx --bun vite dev",
5152 "build": "vite build",
5253 "typecheck": "tsc --noEmit"
5354 }
apps/local/src/routeTree.gen.ts+198−0
@@ -0,0 +1,198 @@
1+/* eslint-disable */
2+
3+// @ts-nocheck
4+
5+// noinspection JSUnusedGlobalSymbols
6+
7+// This file was automatically generated by TanStack Router.
8+// You should NOT make any changes in this file as it will be overwritten.
9+// Additionally, you should also exclude this file from your linter and/or formatter to prevent it from being checked or modified.
10+
11+import { Route as rootRouteImport } from './routes/__root'
12+import { Route as ToolsRouteImport } from './routes/tools'
13+import { Route as SecretsRouteImport } from './routes/secrets'
14+import { Route as IndexRouteImport } from './routes/index'
15+import { Route as V1SplatRouteImport } from './routes/v1.$'
16+import { Route as SourcesNamespaceRouteImport } from './routes/sources.$namespace'
17+import { Route as McpSplatRouteImport } from './routes/mcp.$'
18+import { Route as SourcesAddPluginKeyRouteImport } from './routes/sources.add.$pluginKey'
19+
20+const ToolsRoute = ToolsRouteImport.update({
21+ id: '/tools',
22+ path: '/tools',
23+ getParentRoute: () => rootRouteImport,
24+} as any)
25+const SecretsRoute = SecretsRouteImport.update({
26+ id: '/secrets',
27+ path: '/secrets',
28+ getParentRoute: () => rootRouteImport,
29+} as any)
30+const IndexRoute = IndexRouteImport.update({
31+ id: '/',
32+ path: '/',
33+ getParentRoute: () => rootRouteImport,
34+} as any)
35+const V1SplatRoute = V1SplatRouteImport.update({
36+ id: '/v1/$',
37+ path: '/v1/$',
38+ getParentRoute: () => rootRouteImport,
39+} as any)
40+const SourcesNamespaceRoute = SourcesNamespaceRouteImport.update({
41+ id: '/sources/$namespace',
42+ path: '/sources/$namespace',
43+ getParentRoute: () => rootRouteImport,
44+} as any)
45+const McpSplatRoute = McpSplatRouteImport.update({
46+ id: '/mcp/$',
47+ path: '/mcp/$',
48+ getParentRoute: () => rootRouteImport,
49+} as any)
50+const SourcesAddPluginKeyRoute = SourcesAddPluginKeyRouteImport.update({
51+ id: '/sources/add/$pluginKey',
52+ path: '/sources/add/$pluginKey',
53+ getParentRoute: () => rootRouteImport,
54+} as any)
55+
56+export interface FileRoutesByFullPath {
57+ '/': typeof IndexRoute
58+ '/secrets': typeof SecretsRoute
59+ '/tools': typeof ToolsRoute
60+ '/mcp/$': typeof McpSplatRoute
61+ '/sources/$namespace': typeof SourcesNamespaceRoute
62+ '/v1/$': typeof V1SplatRoute
63+ '/sources/add/$pluginKey': typeof SourcesAddPluginKeyRoute
64+}
65+export interface FileRoutesByTo {
66+ '/': typeof IndexRoute
67+ '/secrets': typeof SecretsRoute
68+ '/tools': typeof ToolsRoute
69+ '/mcp/$': typeof McpSplatRoute
70+ '/sources/$namespace': typeof SourcesNamespaceRoute
71+ '/v1/$': typeof V1SplatRoute
72+ '/sources/add/$pluginKey': typeof SourcesAddPluginKeyRoute
73+}
74+export interface FileRoutesById {
75+ __root__: typeof rootRouteImport
76+ '/': typeof IndexRoute
77+ '/secrets': typeof SecretsRoute
78+ '/tools': typeof ToolsRoute
79+ '/mcp/$': typeof McpSplatRoute
80+ '/sources/$namespace': typeof SourcesNamespaceRoute
81+ '/v1/$': typeof V1SplatRoute
82+ '/sources/add/$pluginKey': typeof SourcesAddPluginKeyRoute
83+}
84+export interface FileRouteTypes {
85+ fileRoutesByFullPath: FileRoutesByFullPath
86+ fullPaths:
87+ | '/'
88+ | '/secrets'
89+ | '/tools'
90+ | '/mcp/$'
91+ | '/sources/$namespace'
92+ | '/v1/$'
93+ | '/sources/add/$pluginKey'
94+ fileRoutesByTo: FileRoutesByTo
95+ to:
96+ | '/'
97+ | '/secrets'
98+ | '/tools'
99+ | '/mcp/$'
100+ | '/sources/$namespace'
101+ | '/v1/$'
102+ | '/sources/add/$pluginKey'
103+ id:
104+ | '__root__'
105+ | '/'
106+ | '/secrets'
107+ | '/tools'
108+ | '/mcp/$'
109+ | '/sources/$namespace'
110+ | '/v1/$'
111+ | '/sources/add/$pluginKey'
112+ fileRoutesById: FileRoutesById
113+}
114+export interface RootRouteChildren {
115+ IndexRoute: typeof IndexRoute
116+ SecretsRoute: typeof SecretsRoute
117+ ToolsRoute: typeof ToolsRoute
118+ McpSplatRoute: typeof McpSplatRoute
119+ SourcesNamespaceRoute: typeof SourcesNamespaceRoute
120+ V1SplatRoute: typeof V1SplatRoute
121+ SourcesAddPluginKeyRoute: typeof SourcesAddPluginKeyRoute
122+}
123+
124+declare module '@tanstack/react-router' {
125+ interface FileRoutesByPath {
126+ '/tools': {
127+ id: '/tools'
128+ path: '/tools'
129+ fullPath: '/tools'
130+ preLoaderRoute: typeof ToolsRouteImport
131+ parentRoute: typeof rootRouteImport
132+ }
133+ '/secrets': {
134+ id: '/secrets'
135+ path: '/secrets'
136+ fullPath: '/secrets'
137+ preLoaderRoute: typeof SecretsRouteImport
138+ parentRoute: typeof rootRouteImport
139+ }
140+ '/': {
141+ id: '/'
142+ path: '/'
143+ fullPath: '/'
144+ preLoaderRoute: typeof IndexRouteImport
145+ parentRoute: typeof rootRouteImport
146+ }
147+ '/v1/$': {
148+ id: '/v1/$'
149+ path: '/v1/$'
150+ fullPath: '/v1/$'
151+ preLoaderRoute: typeof V1SplatRouteImport
152+ parentRoute: typeof rootRouteImport
153+ }
154+ '/sources/$namespace': {
155+ id: '/sources/$namespace'
156+ path: '/sources/$namespace'
157+ fullPath: '/sources/$namespace'
158+ preLoaderRoute: typeof SourcesNamespaceRouteImport
159+ parentRoute: typeof rootRouteImport
160+ }
161+ '/mcp/$': {
162+ id: '/mcp/$'
163+ path: '/mcp/$'
164+ fullPath: '/mcp/$'
165+ preLoaderRoute: typeof McpSplatRouteImport
166+ parentRoute: typeof rootRouteImport
167+ }
168+ '/sources/add/$pluginKey': {
169+ id: '/sources/add/$pluginKey'
170+ path: '/sources/add/$pluginKey'
171+ fullPath: '/sources/add/$pluginKey'
172+ preLoaderRoute: typeof SourcesAddPluginKeyRouteImport
173+ parentRoute: typeof rootRouteImport
174+ }
175+ }
176+}
177+
178+const rootRouteChildren: RootRouteChildren = {
179+ IndexRoute: IndexRoute,
180+ SecretsRoute: SecretsRoute,
181+ ToolsRoute: ToolsRoute,
182+ McpSplatRoute: McpSplatRoute,
183+ SourcesNamespaceRoute: SourcesNamespaceRoute,
184+ V1SplatRoute: V1SplatRoute,
185+ SourcesAddPluginKeyRoute: SourcesAddPluginKeyRoute,
186+}
187+export const routeTree = rootRouteImport
188+ ._addFileChildren(rootRouteChildren)
189+ ._addFileTypes<FileRouteTypes>()
190+
191+import type { getRouter } from './router.tsx'
192+import type { createStart } from '@tanstack/react-start'
193+declare module '@tanstack/react-start' {
194+ interface Register {
195+ ssr: true
196+ router: Awaited<ReturnType<typeof getRouter>>
197+ }
198+}
apps/local/src/router.tsx+10−0
@@ -0,0 +1,10 @@
1+import { createRouter } from "@tanstack/react-router";
2+import { routeTree } from "./routeTree.gen";
3+
4+export const getRouter = () => {
5+ return createRouter({
6+ routeTree,
7+ scrollRestoration: true,
8+ defaultPreloadStaleTime: 0,
9+ });
10+};
apps/local/src/routes/__root.tsx+45−0
@@ -0,0 +1,45 @@
1+import React from "react";
2+import { HeadContent, Outlet, Scripts, createRootRoute } from "@tanstack/react-router";
3+import { ExecutorProvider } from "@executor/react/api/provider";
4+import { Shell } from "../web/shell";
5+import appCss from "@executor/react/globals.css?url";
6+
7+export const Route = createRootRoute({
8+ head: () => ({
9+ meta: [
10+ { charSet: "utf-8" },
11+ { name: "viewport", content: "width=device-width, initial-scale=1" },
12+ { title: "Executor" },
13+ ],
14+ links: [
15+ { rel: "preconnect", href: "https://fonts.googleapis.com" },
16+ { rel: "preconnect", href: "https://fonts.gstatic.com", crossOrigin: "anonymous" },
17+ { rel: "stylesheet", href: "https://fonts.googleapis.com/css2?family=DM+Sans:ital,opsz,wght@0,9..40,300..700;1,9..40,300..700&family=Instrument+Serif&family=JetBrains+Mono:wght@400;500&display=swap" },
18+ { rel: "stylesheet", href: appCss },
19+ ],
20+ }),
21+ component: RootComponent,
22+ shellComponent: RootDocument,
23+});
24+
25+function RootDocument({ children }: { children: React.ReactNode }) {
26+ return (
27+ <html lang="en">
28+ <head>
29+ <HeadContent />
30+ </head>
31+ <body>
32+ {children}
33+ <Scripts />
34+ </body>
35+ </html>
36+ );
37+}
38+
39+function RootComponent() {
40+ return (
41+ <ExecutorProvider>
42+ <Shell />
43+ </ExecutorProvider>
44+ );
45+}
apps/local/src/routes/index.tsx+6−0
@@ -0,0 +1,6 @@
1+import { createFileRoute } from "@tanstack/react-router";
2+import { SourcesPage } from "@executor/react/pages/sources";
3+
4+export const Route = createFileRoute("/")({
5+ component: SourcesPage,
6+});
apps/local/src/routes/mcp.$.ts+13−0
@@ -0,0 +1,13 @@
1+import { createFileRoute } from "@tanstack/react-router";
2+import { handleMcpRequest } from "../server/api-handler";
3+
4+export const Route = createFileRoute("/mcp/$")({
5+ server: {
6+ handlers: {
7+ GET: ({ request }) => handleMcpRequest(request),
8+ POST: ({ request }) => handleMcpRequest(request),
9+ PUT: ({ request }) => handleMcpRequest(request),
10+ DELETE: ({ request }) => handleMcpRequest(request),
11+ },
12+ },
13+});
apps/local/src/routes/secrets.tsx+6−0
@@ -0,0 +1,6 @@
1+import { createFileRoute } from "@tanstack/react-router";
2+import { SecretsPage } from "@executor/react/pages/secrets";
3+
4+export const Route = createFileRoute("/secrets")({
5+ component: SecretsPage,
6+});
apps/local/src/routes/sources.$namespace.tsx+9−0
@@ -0,0 +1,9 @@
1+import { createFileRoute } from "@tanstack/react-router";
2+import { SourceDetailPage } from "@executor/react/pages/source-detail";
3+
4+export const Route = createFileRoute("/sources/$namespace")({
5+ component: () => {
6+ const { namespace } = Route.useParams();
7+ return <SourceDetailPage namespace={namespace} />;
8+ },
9+});
apps/local/src/routes/sources.add.$pluginKey.tsx+19−0
@@ -0,0 +1,19 @@
1+import { Schema } from "effect";
2+import { createFileRoute } from "@tanstack/react-router";
3+import { SourcesAddPage } from "@executor/react/pages/sources-add";
4+
5+const SearchParams = Schema.standardSchemaV1(
6+ Schema.Struct({
7+ url: Schema.optional(Schema.String),
8+ preset: Schema.optional(Schema.String),
9+ }),
10+);
11+
12+export const Route = createFileRoute("/sources/add/$pluginKey")({
13+ validateSearch: SearchParams,
14+ component: () => {
15+ const { pluginKey } = Route.useParams();
16+ const { url, preset } = Route.useSearch();
17+ return <SourcesAddPage pluginKey={pluginKey} url={url} preset={preset} />;
18+ },
19+});
apps/local/src/routes/tools.tsx+6−0
@@ -0,0 +1,6 @@
1+import { createFileRoute } from "@tanstack/react-router";
2+import { ToolsPage } from "@executor/react/pages/tools";
3+
4+export const Route = createFileRoute("/tools")({
5+ component: ToolsPage,
6+});
apps/local/src/routes/v1.$.ts+14−0
@@ -0,0 +1,14 @@
1+import { createFileRoute } from "@tanstack/react-router";
2+import { handleApiRequest } from "../server/api-handler";
3+
4+export const Route = createFileRoute("/v1/$")({
5+ server: {
6+ handlers: {
7+ GET: ({ request }) => handleApiRequest(request),
8+ POST: ({ request }) => handleApiRequest(request),
9+ PUT: ({ request }) => handleApiRequest(request),
10+ DELETE: ({ request }) => handleApiRequest(request),
11+ PATCH: ({ request }) => handleApiRequest(request),
12+ },
13+ },
14+});
apps/local/src/server/api-handler.ts+29−0
@@ -0,0 +1,29 @@
1+type ServerHandlers = {
2+ readonly api: {
3+ readonly handler: (request: Request) => Promise<Response>;
4+ readonly dispose: () => Promise<void>;
5+ };
6+ readonly mcp: {
7+ readonly handleRequest: (request: Request) => Promise<Response>;
8+ readonly close: () => Promise<void>;
9+ };
10+};
11+
12+let handlersPromise: Promise<ServerHandlers> | null = null;
13+
14+const getHandlers = () => {
15+ if (!handlersPromise) {
16+ handlersPromise = import("./main").then((mod) => mod.createServerHandlers());
17+ }
18+ return handlersPromise;
19+};
20+
21+export const handleApiRequest = async (request: Request): Promise<Response> => {
22+ const handlers = await getHandlers();
23+ return handlers.api.handler(request);
24+};
25+
26+export const handleMcpRequest = async (request: Request): Promise<Response> => {
27+ const handlers = await getHandlers();
28+ return handlers.mcp.handleRequest(request);
29+};
apps/local/src/server/dev-backend.ts+0−17
@@ -1,17 +0,0 @@
1−import { createServerHandlers, type ServerHandlers } from "./main";
2−
3−export type HotBackend = ServerHandlers & {
4− readonly dispose: () => Promise<void>;
5−};
6−
7−export const createHotBackend = async (): Promise<HotBackend> => {
8− const handlers = await createServerHandlers();
9−
10− return {
11− ...handlers,
12− dispose: async () => {
13− await handlers.api.dispose().catch(() => undefined);
14− await handlers.mcp.close().catch(() => undefined);
15− },
16− };
17−};
apps/local/src/vite-env.d.ts+1−0
@@ -0,0 +1 @@
1+/// <reference types="vite/client" />
apps/local/src/web/App.tsx+0−6
@@ -1,6 +0,0 @@
1−import { RouterProvider } from "@tanstack/react-router";
2−import { router } from "./router";
3−
4−export function App() {
5− return <RouterProvider router={router} />;
6−}
apps/local/src/web/main.tsx+0−7
@@ -1,7 +0,0 @@
1−import React from "react";
2−import { createRoot } from "react-dom/client";
3−import "@executor/react/globals.css";
4−import { App } from "./App";
5−
6−const root = createRoot(document.getElementById("root")!);
7−root.render(<App />);
apps/local/src/web/router.tsx+0−93
@@ -1,93 +0,0 @@
1−import {
2− createRouter,
3− createRootRoute,
4− createRoute,
5−} from "@tanstack/react-router";
6−import { ExecutorProvider } from "@executor/react/api/provider";
7−import { ToolsPage } from "@executor/react/pages/tools";
8−import { SourcesPage } from "@executor/react/pages/sources";
9−import { SourcesAddPage } from "@executor/react/pages/sources-add";
10−import { SourceDetailPage } from "@executor/react/pages/source-detail";
11−import { SecretsPage } from "@executor/react/pages/secrets";
12−import { Shell } from "./shell";
13−
14−// ---------------------------------------------------------------------------
15−// Root layout — Shell renders <Outlet /> directly
16−// ---------------------------------------------------------------------------
17−
18−const rootRoute = createRootRoute({
19− component: () => (
20− <ExecutorProvider>
21− <Shell />
22− </ExecutorProvider>
23− ),
24−});
25−
26−// ---------------------------------------------------------------------------
27−// Routes
28−// ---------------------------------------------------------------------------
29−
30−const indexRoute = createRoute({
31− getParentRoute: () => rootRoute,
32− path: "/",
33− component: SourcesPage,
34−});
35−
36−const toolsRoute = createRoute({
37− getParentRoute: () => rootRoute,
38− path: "/tools",
39− component: ToolsPage,
40−});
41−
42−const sourcesAddRoute = createRoute({
43− getParentRoute: () => rootRoute,
44− path: "/sources/add/$pluginKey",
45− validateSearch: (
46− search: Record<string, unknown>,
47− ): { url?: string; preset?: string } => ({
48− url: typeof search.url === "string" ? search.url : undefined,
49− preset: typeof search.preset === "string" ? search.preset : undefined,
50− }),
51− component: () => {
52− const { pluginKey } = sourcesAddRoute.useParams();
53− const { url, preset } = sourcesAddRoute.useSearch();
54− return (
55− <SourcesAddPage pluginKey={pluginKey} url={url} preset={preset} />
56− );
57− },
58−});
59−
60−const sourceDetailRoute = createRoute({
61− getParentRoute: () => rootRoute,
62− path: "/sources/$namespace",
63− component: () => {
64− const { namespace } = sourceDetailRoute.useParams();
65− return <SourceDetailPage namespace={namespace} />;
66− },
67−});
68−
69−const secretsRoute = createRoute({
70− getParentRoute: () => rootRoute,
71− path: "/secrets",
72− component: SecretsPage,
73−});
74−
75−// ---------------------------------------------------------------------------
76−// Router
77−// ---------------------------------------------------------------------------
78−
79−const routeTree = rootRoute.addChildren([
80− indexRoute,
81− toolsRoute,
82− sourcesAddRoute,
83− sourceDetailRoute,
84− secretsRoute,
85−]);
86−
87−export const router = createRouter({ routeTree });
88−
89−declare module "@tanstack/react-router" {
90− interface Register {
91− router: typeof router;
92− }
93−}
apps/local/src/web/shell.tsx+0−1
@@ -450,7 +450,6 @@ export function Shell() { · 449 unmodified lines
450450 <div className="w-8 shrink-0" />
451451 </div>
452452
453− {/* Outlet — pages control their own padding/scroll */}
454453 <Outlet />
455454 </main>
456455 </div>
apps/local/vite.config.ts+18−181
@@ -1,86 +1,9 @@
11 import { readFileSync } from "node:fs";
2−import { resolve } from "node:path";
32 import { defineConfig } from "vite";
3+import { tanstackStart } from "@tanstack/react-start/plugin/vite";
44 import react from "@vitejs/plugin-react";
55 import tailwindcss from "@tailwindcss/vite";
66
7−type HotBackend = {
8− readonly api: {
9− readonly handler: (request: Request) => Promise<Response>;
10− readonly dispose: () => Promise<void>;
11− };
12− readonly mcp: {
13− readonly handleRequest: (request: Request) => Promise<Response>;
14− readonly close: () => Promise<void>;
15− };
16− readonly dispose: () => Promise<void>;
17−};
18−
19−const DEV_BACKEND_MODULE_ID = `/@fs/${resolve(
20− process.cwd(),
21− "src/server/dev-backend.ts",
22−).replace(/\\/g, "/")}`;
23−
24−// Build a Web Request from a Node IncomingMessage
25−const toWebRequest = async (
26− req: import("http").IncomingMessage,
27−): Promise<Request> => {
28− const headers = new Headers();
29− for (const [key, value] of Object.entries(req.headers)) {
30− if (value === undefined) continue;
31− if (Array.isArray(value)) {
32− for (const v of value) headers.append(key, v);
33− } else {
34− headers.set(key, value);
35− }
36− }
37−
38− const host = req.headers.host ?? "localhost";
39− const url = `http://${host}${req.url}`;
40−
41− return new Request(
42− url,
43− {
44− method: req.method,
45− headers,
46− body:
47− req.method !== "GET" && req.method !== "HEAD"
48− ? (await new Promise<Buffer>((resolve) => {
49− const chunks: Buffer[] = [];
50− req.on("data", (c: Buffer) => chunks.push(c));
51− req.on("end", () => resolve(Buffer.concat(chunks)));
52− }) as unknown as BodyInit)
53− : undefined,
54− duplex: "half" as const,
55− } as RequestInit & { duplex: "half" },
56− );
57−};
58−
59−// Pipe a Web Response back to a Node ServerResponse, streaming if needed
60−const sendWebResponse = async (
61− webRes: Response,
62− nodeRes: import("http").ServerResponse,
63−) => {
64− nodeRes.statusCode = webRes.status;
65− webRes.headers.forEach((value, key) => nodeRes.setHeader(key, value));
66−
67− if (!webRes.body) {
68− nodeRes.end();
69− return;
70− }
71−
72− const reader = webRes.body.getReader();
73− try {
74− for (;;) {
75− const { done, value } = await reader.read();
76− if (done) break;
77− nodeRes.write(value);
78− }
79− } finally {
80− nodeRes.end();
81− }
82−};
83−
847 const rootPackage = JSON.parse(
858 readFileSync(new URL("../../package.json", import.meta.url), "utf8"),
869 ) as { version: string; homepage?: string; repository?: string | { url?: string } };
@@ -106,111 +29,25 @@ export default defineConfig({ · 19 unmodified lines
10629 },
10730 resolve: {
10831 dedupe: ["react", "react-dom"],
32+ tsconfigPaths: true,
33+ },
34+ server: {
35+ port: parseInt(process.env.PORT ?? "5173", 10),
36+ host: "127.0.0.1",
37+ },
38+ ssr: {
39+ external: true,
40+ },
41+ optimizeDeps: {
42+ rolldownOptions: {
43+ external: [/^@napi-rs\//],
44+ },
10945 },
11046 plugins: [
111− react(),
11247 tailwindcss(),
113− {
114− name: "executor-api",
115− configureServer(server) {
116− let backendPromise: Promise<HotBackend> | null = null;
117− let reloadPromise: Promise<void> | null = null;
118−
119− const loadBackend = () =>
120− server
121− .ssrLoadModule(DEV_BACKEND_MODULE_ID)
122− .then((mod) => mod.createHotBackend() as Promise<HotBackend>);
123−
124− const getBackend = () => {
125− if (!backendPromise) {
126− backendPromise = loadBackend();
127− }
128− return backendPromise;
129− };
130−
131− const shouldReloadBackend = (file: string) =>
132− /\.(ts|tsx)$/.test(file) &&
133− !file.includes("/src/web/") &&
134− (
135− file.includes("/src/server/") ||
136− file.includes("/packages/core/") ||
137− file.includes("/packages/plugins/") ||
138− file.includes("/packages/hosts/")
139− );
140−
141− server.httpServer?.once("close", () => {
142− const pending = backendPromise;
143− backendPromise = null;
144− void pending?.then((backend) => backend.dispose()).catch(() => undefined);
145− });
146−
147− server.watcher.on("change", (file) => {
148− if (!shouldReloadBackend(file) || reloadPromise) {
149− return;
150− }
151−
152− reloadPromise = (async () => {
153− server.config.logger.info(`[executor-api] hot reloading backend: ${file}`);
154−
155− const previous = await getBackend().catch(() => null);
156−
157− server.moduleGraph.invalidateAll();
158− backendPromise = loadBackend();
159−
160− await backendPromise;
161− await previous?.dispose().catch(() => undefined);
162−
163− server.ws.send({
164− type: "custom",
165− event: "executor:backend-updated",
166− data: { file },
167− });
168− })()
169− .catch((error) => {
170− server.config.logger.error(
171− `[executor-api] backend reload failed: ${error instanceof Error ? error.message : String(error)}`,
172− );
173− })
174− .finally(() => {
175− reloadPromise = null;
176− });
177− });
178−
179− // Host-header allowlist — blocks DNS rebinding attacks
180− const ALLOWED_HOSTS = new Set(["localhost", "127.0.0.1", "[::1]", "::1"]);
181−
182− server.middlewares.use(async (req, res, next) => {
183− const url = req.url ?? "/";
184−
185− const isApi =
186− url.startsWith("/v1/") ||
187− url.startsWith("/docs") ||
188− url === "/openapi.json";
189− const isMcp = url.startsWith("/mcp");
190−
191− if (!isApi && !isMcp) return next();
192−
193− // Validate host header to prevent DNS rebinding
194− const host = req.headers.host;
195− if (host) {
196− const hostname = host.replace(/:\d+$/, "");
197− if (!ALLOWED_HOSTS.has(hostname)) {
198− res.statusCode = 403;
199− res.end("Forbidden");
200− return;
201− }
202− }
203−
204− const backend = await getBackend();
205− const request = await toWebRequest(req);
206−
207− const response = isMcp
208− ? await backend.mcp.handleRequest(request)
209− : await backend.api.handler(request);
210−
211− await sendWebResponse(response, res);
212− });
213− },
214− },
48+ tanstackStart({
49+ spa: { enabled: true },
50+ }),
51+ ...react(),
21552 ],
21653 });
bun.lock+235−73
@@ -18,7 +18,7 @@ · 17 unmodified lines
1818 },
1919 "apps/cli": {
2020 "name": "executor",
21− "version": "1.4.1",
21+ "version": "1.4.2",
2222 "bin": {
2323 "executor": "./bin/executor.ts",
2424 },
@@ -35,7 +35,7 @@ · 10 unmodified lines
3535 },
3636 "devDependencies": {
3737 "bun-types": "catalog:",
38− "typescript": "^5.9.3",
38+ "typescript": "catalog:",
3939 },
4040 },
4141 "apps/cloud": {
@@ -53,24 +53,25 @@ · 11 unmodified lines
5353 "@executor/react": "workspace:*",
5454 "@executor/sdk": "workspace:*",
5555 "@executor/storage-postgres": "workspace:*",
56− "@tanstack/react-router": "^1.168.10",
56+ "@tanstack/react-router": "catalog:",
57+ "@tanstack/react-start": "catalog:",
5758 "@workos-inc/node": "^7.0.0",
5859 "drizzle-orm": "catalog:",
5960 "effect": "catalog:",
6061 "pg": "^8.16.0",
61− "react": "^19.1.0",
62− "react-dom": "^19.1.0",
62+ "react": "catalog:",
63+ "react-dom": "catalog:",
6364 },
6465 "devDependencies": {
6566 "@electric-sql/pglite": "^0.4.3",
66− "@tailwindcss/vite": "^4.1.10",
67+ "@tailwindcss/vite": "catalog:",
6768 "@types/pg": "^8.15.4",
68− "@types/react": "^19.1.0",
69− "@types/react-dom": "^19.1.0",
70− "@vitejs/plugin-react": "^4.5.2",
69+ "@types/react": "catalog:",
70+ "@types/react-dom": "catalog:",
71+ "@vitejs/plugin-react": "catalog:",
7172 "portless": "^0.3.0",
72− "typescript": "^5.9.3",
73− "vite": "^6.3.5",
73+ "typescript": "catalog:",
74+ "vite": "catalog:",
7475 },
7576 },
7677 "apps/desktop": {
@@ -80,7 +81,7 @@ · 3 unmodified lines
8081 "@types/node": "catalog:",
8182 "electron": "35.7.5",
8283 "electron-builder": "^26.0.12",
83− "typescript": "^5.9.3",
84+ "typescript": "catalog:",
8485 },
8586 },
8687 "apps/local": {
@@ -108,23 +109,24 @@ · 21 unmodified lines
108109 "@modelcontextprotocol/sdk": "^1.12.1",
109110 "@shikijs/langs": "^4.0.2",
110111 "@shikijs/themes": "^4.0.2",
111− "@tanstack/react-router": "^1.168.10",
112+ "@tanstack/react-router": "catalog:",
113+ "@tanstack/react-start": "catalog:",
112114 "effect": "catalog:",
113− "react": "^19.1.0",
114− "react-dom": "^19.1.0",
115+ "react": "catalog:",
116+ "react-dom": "catalog:",
115117 "shiki": "^4.0.2",
116118 "streamdown": "^2.5.0",
117− "tailwindcss": "^4.1.10",
119+ "tailwindcss": "catalog:",
118120 },
119121 "devDependencies": {
120− "@tailwindcss/vite": "^4.1.10",
122+ "@tailwindcss/vite": "catalog:",
121123 "@types/node": "catalog:",
122− "@types/react": "^19.1.0",
123− "@types/react-dom": "^19.1.0",
124− "@vitejs/plugin-react": "^4.5.2",
124+ "@types/react": "catalog:",
125+ "@types/react-dom": "catalog:",
126+ "@vitejs/plugin-react": "catalog:",
125127 "bun-types": "catalog:",
126− "typescript": "^5.9.3",
127− "vite": "^6.3.5",
128+ "typescript": "catalog:",
129+ "vite": "catalog:",
128130 },
129131 },
130132 "apps/marketing": {
@@ -133,8 +135,13 @@ · 2 unmodified lines
133135 "dependencies": {
134136 "@astrojs/tailwind": "^6.0.2",
135137 "@astrojs/vercel": "^10.0.4",
138+ "@executor/plugin-google-discovery": "workspace:*",
139+ "@executor/plugin-graphql": "workspace:*",
140+ "@executor/plugin-openapi": "workspace:*",
141+ "@executor/sdk": "workspace:*",
136142 "@tailwindcss/vite": "^4.2.2",
137143 "astro": "^6.1.3",
144+ "effect": "^3.14.16",
138145 "tailwindcss": "^4.2.2",
139146 },
140147 },
@@ -150,7 +157,7 @@ · 9 unmodified lines
150157 "devDependencies": {
151158 "@types/node": "catalog:",
152159 "bun-types": "catalog:",
153− "typescript": "^5.9.3",
160+ "typescript": "catalog:",
154161 },
155162 },
156163 "packages/core/config": {
@@ -165,7 +172,7 @@ · 8 unmodified lines
165172 "devDependencies": {
166173 "@effect/platform-node": "catalog:",
167174 "@effect/vitest": "catalog:",
168− "typescript": "latest",
175+ "typescript": "catalog:",
169176 "vitest": "catalog:",
170177 },
171178 },
@@ -193,7 +200,7 @@ · 21 unmodified lines
193200 },
194201 "devDependencies": {
195202 "@effect/vitest": "catalog:",
196− "typescript": "latest",
203+ "typescript": "catalog:",
197204 "vitest": "catalog:",
198205 },
199206 },
@@ -209,7 +216,7 @@ · 9 unmodified lines
209216 "@effect/experimental": "catalog:",
210217 "@effect/sql-sqlite-node": "catalog:",
211218 "@effect/vitest": "catalog:",
212− "typescript": "^5.9.3",
219+ "typescript": "catalog:",
213220 "vitest": "catalog:",
214221 },
215222 },
@@ -229,7 +236,7 @@ · 13 unmodified lines
229236 "@electric-sql/pglite": "^0.4.3",
230237 "@types/pg": "^8.15.4",
231238 "drizzle-kit": "^0.31.0",
232− "typescript": "^5.9.3",
239+ "typescript": "catalog:",
233240 "vitest": "catalog:",
234241 },
235242 },
@@ -337,16 +344,16 @@ · 101 unmodified lines
337344 "@effect/vitest": "catalog:",
338345 "@executor/react": "workspace:*",
339346 "@types/node": "catalog:",
340− "@types/react": "^19.1.0",
347+ "@types/react": "catalog:",
341348 "bun-types": "catalog:",
342− "react": "^19.1.0",
349+ "react": "catalog:",
343350 "vitest": "catalog:",
344351 },
345352 "peerDependencies": {
346353 "@effect-atom/atom-react": "^0.5.0",
347354 "@executor/react": "workspace:*",
348− "@tanstack/react-router": "^1.168.10",
349− "react": "^19.1.0",
355+ "@tanstack/react-router": "catalog:",
356+ "react": "catalog:",
350357 },
351358 "optionalPeers": [
352359 "@effect-atom/atom-react",
@@ -370,17 +377,17 @@ · 17 unmodified lines
370377 "@executor/api": "workspace:*",
371378 "@executor/react": "workspace:*",
372379 "@types/node": "catalog:",
373− "@types/react": "^19.1.0",
380+ "@types/react": "catalog:",
374381 "bun-types": "catalog:",
375− "react": "^19.1.0",
382+ "react": "catalog:",
376383 "vitest": "catalog:",
377384 },
378385 "peerDependencies": {
379386 "@effect-atom/atom-react": "^0.5.0",
380387 "@executor/api": "workspace:*",
381388 "@executor/react": "workspace:*",
382− "@tanstack/react-router": "^1.168.10",
383− "react": "^19.1.0",
389+ "@tanstack/react-router": "catalog:",
390+ "react": "catalog:",
384391 },
385392 "optionalPeers": [
386393 "@effect-atom/atom-react",
@@ -421,9 +428,9 @@ · 34 unmodified lines
421428 "@executor/api": "workspace:*",
422429 "@executor/react": "workspace:*",
423430 "@types/node": "catalog:",
424− "@types/react": "^19.1.0",
431+ "@types/react": "catalog:",
425432 "bun-types": "catalog:",
426− "react": "^19.1.0",
433+ "react": "catalog:",
427434 "vitest": "catalog:",
428435 "zod": "^4.3.6",
429436 },
@@ -431,8 +438,8 @@ · 1 unmodified line
431438 "@effect-atom/atom-react": "^0.5.0",
432439 "@executor/api": "workspace:*",
433440 "@executor/react": "workspace:*",
434− "@tanstack/react-router": "^1.168.10",
435− "react": "^19.1.0",
441+ "@tanstack/react-router": "catalog:",
442+ "react": "catalog:",
436443 },
437444 "optionalPeers": [
438445 "@effect-atom/atom-react",
@@ -457,9 +464,9 @@ · 18 unmodified lines
457464 "devDependencies": {
458465 "@effect/vitest": "catalog:",
459466 "@types/node": "catalog:",
460− "@types/react": "^19.1.0",
467+ "@types/react": "catalog:",
461468 "bun-types": "catalog:",
462− "react": "^19.1.0",
469+ "react": "catalog:",
463470 "vitest": "catalog:",
464471 },
465472 "peerDependencies": {
@@ -491,17 +498,17 @@ · 25 unmodified lines
491498 "@executor/api": "workspace:*",
492499 "@executor/react": "workspace:*",
493500 "@types/node": "catalog:",
494− "@types/react": "^19.1.0",
501+ "@types/react": "catalog:",
495502 "bun-types": "catalog:",
496− "react": "^19.1.0",
503+ "react": "catalog:",
497504 "vitest": "catalog:",
498505 },
499506 "peerDependencies": {
500507 "@effect-atom/atom-react": "^0.5.0",
501508 "@executor/api": "workspace:*",
502509 "@executor/react": "workspace:*",
503− "@tanstack/react-router": "^1.168.10",
504− "react": "^19.1.0",
510+ "@tanstack/react-router": "catalog:",
511+ "react": "catalog:",
505512 },
506513 "optionalPeers": [
507514 "@effect-atom/atom-react",
@@ -534,7 +541,7 @@ · 26 unmodified lines
534541 "lucide-react": "^1.7.0",
535542 "next-themes": "^0.4.6",
536543 "radix-ui": "^1.4.3",
537− "react": "^19.1.0",
544+ "react": "catalog:",
538545 "react-day-picker": "^9.14.0",
539546 "react-hook-form": "^7.72.0",
540547 "react-resizable-panels": "^4",
@@ -548,10 +555,10 @@ · 7 unmodified lines
548555 },
549556 "devDependencies": {
550557 "@types/node": "catalog:",
551− "@types/react": "^19.1.0",
558+ "@types/react": "catalog:",
552559 "hast-util-to-jsx-runtime": "^2.3.6",
553− "tailwindcss": "^4.1.10",
554− "typescript": "^5.9.3",
560+ "tailwindcss": "catalog:",
561+ "typescript": "catalog:",
555562 },
556563 },
557564 },
@@ -566,10 +573,21 @@ · 8 unmodified lines
566573 "@effect/sql-sqlite-bun": "^0.52.0",
567574 "@effect/sql-sqlite-node": "^0.52.0",
568575 "@effect/vitest": "^0.27.0",
576+ "@tailwindcss/vite": "^4.2.2",
577+ "@tanstack/react-router": "^1.168.10",
578+ "@tanstack/react-start": "^1.167.16",
569579 "@types/node": "^24.3.1",
580+ "@types/react": "^19.1.0",
581+ "@types/react-dom": "^19.1.0",
582+ "@vitejs/plugin-react": "^6.0.1",
570583 "bun-types": "^1.2.22",
571584 "drizzle-orm": "^0.44.0",
572585 "effect": "^3.21.0",
586+ "react": "^19.1.0",
587+ "react-dom": "^19.1.0",
588+ "tailwindcss": "^4.2.2",
589+ "typescript": "^5.9.3",
590+ "vite": "^8.0.0",
573591 "vitest": "^3.2.4",
574592 },
575593 "packages": {
@@ -605,7 +623,7 @@ · 29 unmodified lines
605623
606624 "@astrojs/vercel": ["@astrojs/vercel@10.0.4", "", { "dependencies": { "@astrojs/internal-helpers": "0.8.0", "@vercel/analytics": "^1.6.1", "@vercel/functions": "^3.4.3", "@vercel/nft": "^1.3.2", "@vercel/routing-utils": "^5.3.3", "esbuild": "^0.27.3", "tinyglobby": "^0.2.15" }, "peerDependencies": { "astro": "^6.0.0" } }, "sha512-+kxbLKCimr9ivqXTldE3JyXB6Ks7WU6C8jcZGt+CLM9N1IVCWck9ustz3Hd/OGROQpzRATLVvrlbwyeM7Gycpw=="],
607625
608− "@babel/code-frame": ["@babel/code-frame@7.29.0", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.28.5", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" } }, "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw=="],
626+ "@babel/code-frame": ["@babel/code-frame@7.27.1", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.27.1", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" } }, "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg=="],
609627
610628 "@babel/compat-data": ["@babel/compat-data@7.29.0", "", {}, "sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg=="],
611629
@@ -633,9 +651,9 @@ · 21 unmodified lines
633651
634652 "@babel/parser": ["@babel/parser@7.29.2", "", { "dependencies": { "@babel/types": "^7.29.0" }, "bin": "./bin/babel-parser.js" }, "sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA=="],
635653
636− "@babel/plugin-transform-react-jsx-self": ["@babel/plugin-transform-react-jsx-self@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw=="],
654+ "@babel/plugin-syntax-jsx": ["@babel/plugin-syntax-jsx@7.28.6", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-wgEmr06G6sIpqr8YDwA2dSRTE3bJ+V0IfpzfSY3Lfgd7YWOaAdlykvJi13ZKBt8cZHfgH1IXN+CL656W3uUa4w=="],
637655
638− "@babel/plugin-transform-react-jsx-source": ["@babel/plugin-transform-react-jsx-source@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw=="],
656+ "@babel/plugin-syntax-typescript": ["@babel/plugin-syntax-typescript@7.28.6", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-+nDNmQye7nlnuuHDboPbGm00Vqg3oO8niRRL27/4LYHUsHYh0zJ1xWOz0uRwNFmM1Avzk8wZbc6rdiYhomzv/A=="],
639657
640658 "@babel/runtime": ["@babel/runtime@7.29.2", "", {}, "sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g=="],
641659
@@ -765,8 +783,12 @@ · 123 unmodified lines
765783
766784 "@electron/windows-sign": ["@electron/windows-sign@1.2.2", "", { "dependencies": { "cross-dirname": "^0.1.0", "debug": "^4.3.4", "fs-extra": "^11.1.1", "minimist": "^1.2.8", "postject": "^1.0.0-alpha.6" }, "bin": { "electron-windows-sign": "bin/electron-windows-sign.js" } }, "sha512-dfZeox66AvdPtb2lD8OsIIQh12Tp0GNCRUDfBHIKGpbmopZto2/A8nSpYYLoedPIHpqkeblZ/k8OV0Gy7PYuyQ=="],
767785
786+ "@emnapi/core": ["@emnapi/core@1.9.1", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.0", "tslib": "^2.4.0" } }, "sha512-mukuNALVsoix/w1BJwFzwXBN/dHeejQtuVzcDsfOEsdpCumXb/E9j8w11h5S54tT1xhifGfbbSm/ICrObRb3KA=="],
787+
768788 "@emnapi/runtime": ["@emnapi/runtime@1.9.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-VYi5+ZVLhpgK4hQ0TAjiQiZ6ol0oe4mBx7mVv7IflsiEp0OWoVsp/+f9Vc1hOhE0TtkORVrI1GvzyreqpgWtkA=="],
769789
790+ "@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.2.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-N10dEJNSsUx41Z6pZsXU8FjPjpBEplgH24sfkmITrBED1/U2Esum9F3lfLrMjKHHjmi557zQn7kR9R+XWXu5Rg=="],
791+
770792 "@esbuild-kit/core-utils": ["@esbuild-kit/core-utils@3.3.2", "", { "dependencies": { "esbuild": "~0.18.20", "source-map-support": "^0.5.21" } }, "sha512-sPRAnw9CdSsRmEtnsl2WXWdyquogVpB3yZ3dgwJfe8zrOzTsV7cJvmwrKVa+0ma5BoiGJ+BoqkMvawbayKUsqQ=="],
771793
772794 "@esbuild-kit/esm-loader": ["@esbuild-kit/esm-loader@2.6.5", "", { "dependencies": { "@esbuild-kit/core-utils": "^3.3.2", "get-tsconfig": "^4.7.0" } }, "sha512-FxEMIkJKnodyA1OaCUoEvbYRkoZlLZ4d/eXFu9Fh8CbBBgP5EmZxrfTRyN0qpXZ4vOvqnE5YdRdcrmUUXuU+dA=="],
@@ -1013,6 +1035,8 @@ · 240 unmodified lines
10131035
10141036 "@napi-rs/keyring-win32-x64-msvc": ["@napi-rs/keyring-win32-x64-msvc@1.2.0", "", { "os": "win32", "cpu": "x64" }, "sha512-xFlx/TsmqmCwNU9v+AVnEJgoEAlBYgzFF5Ihz1rMpPAt4qQWWkMd4sCyM1gMJ1A/GnRqRegDiQpwaxGUHFtFbA=="],
10151037
1038+ "@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.1.2", "", { "dependencies": { "@tybys/wasm-util": "^0.10.1" }, "peerDependencies": { "@emnapi/core": "^1.7.1", "@emnapi/runtime": "^1.7.1" } }, "sha512-sNXv5oLJ7ob93xkZ1XnxisYhGYXfaG9f65/ZgYuAu3qt7b3NadcOEhLvx28hv31PgX8SZJRYrAIPQilQmFpLVw=="],
1039+
10161040 "@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g=="],
10171041
10181042 "@nodelib/fs.stat": ["@nodelib/fs.stat@2.0.5", "", {}, "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A=="],
@@ -1023,10 +1047,20 @@ · 4 unmodified lines
10231047
10241048 "@npmcli/fs": ["@npmcli/fs@4.0.0", "", { "dependencies": { "semver": "^7.3.5" } }, "sha512-/xGlezI6xfGO9NwuJlnwz/K14qD1kCSAGtacBHnGzeAIuJGazcp45KP5NuyARXoKb7cwulAGWVsbeSxdG/cb0Q=="],
10251049
1050+ "@oozcitak/dom": ["@oozcitak/dom@2.0.2", "", { "dependencies": { "@oozcitak/infra": "^2.0.2", "@oozcitak/url": "^3.0.0", "@oozcitak/util": "^10.0.0" } }, "sha512-GjpKhkSYC3Mj4+lfwEyI1dqnsKTgwGy48ytZEhm4A/xnH/8z9M3ZVXKr/YGQi3uCLs1AEBS+x5T2JPiueEDW8w=="],
1051+
1052+ "@oozcitak/infra": ["@oozcitak/infra@2.0.2", "", { "dependencies": { "@oozcitak/util": "^10.0.0" } }, "sha512-2g+E7hoE2dgCz/APPOEK5s3rMhJvNxSMBrP+U+j1OWsIbtSpWxxlUjq1lU8RIsFJNYv7NMlnVsCuHcUzJW+8vA=="],
1053+
1054+ "@oozcitak/url": ["@oozcitak/url@3.0.0", "", { "dependencies": { "@oozcitak/infra": "^2.0.2", "@oozcitak/util": "^10.0.0" } }, "sha512-ZKfET8Ak1wsLAiLWNfFkZc/BraDccuTJKR6svTYc7sVjbR+Iu0vtXdiDMY4o6jaFl5TW2TlS7jbLl4VovtAJWQ=="],
1055+
1056+ "@oozcitak/util": ["@oozcitak/util@10.0.0", "", {}, "sha512-hAX0pT/73190NLqBPPWSdBVGtbY6VOhWYK3qqHqtXQ1gK7kS2yz4+ivsN07hpJ6I3aeMtKP6J6npsEKOAzuTLA=="],
1057+
10261058 "@opentelemetry/semantic-conventions": ["@opentelemetry/semantic-conventions@1.40.0", "", {}, "sha512-cifvXDhcqMwwTlTK04GBNeIe7yyo28Mfby85QXFe1Yk8nmi36Ab/5UQwptOx84SsoGNRg+EVSjwzfSZMy6pmlw=="],
10271059
10281060 "@oslojs/encoding": ["@oslojs/encoding@1.1.0", "", {}, "sha512-70wQhgYmndg4GCPxPPxPGevRKqTIJ2Nh4OkiMWmDAVYsTQ+Ta7Sq+rPevXyXGdzr30/qZBnyOalCszoMxlyldQ=="],
10291061
1062+ "@oxc-project/types": ["@oxc-project/types@0.122.0", "", {}, "sha512-oLAl5kBpV4w69UtFZ9xqcmTi+GENWOcPF7FCrczTiBbmC0ibXxCwyvZGbO39rCVEuLGAZM84DH0pUIyyv/YJzA=="],
1063+
10301064 "@oxlint/binding-android-arm-eabi": ["@oxlint/binding-android-arm-eabi@1.58.0", "", { "os": "android", "cpu": "arm" }, "sha512-1T7UN3SsWWxpWyWGn1cT3ASNJOo+pI3eUkmEl7HgtowapcV8kslYpFQcYn431VuxghXakPNlbjRwhqmR37PFOg=="],
10311065
10321066 "@oxlint/binding-android-arm64": ["@oxlint/binding-android-arm64@1.58.0", "", { "os": "android", "cpu": "arm64" }, "sha512-GryzujxuiRv2YFF7bRy8mKcxlbuAN+euVUtGJt9KKbLT8JBUIosamVhcthLh+VEr6KE6cjeVMAQxKAzJcoN7dg=="],
@@ -1223,7 +1257,37 @@ · 190 unmodified lines
12231257
12241258 "@reduxjs/toolkit": ["@reduxjs/toolkit@2.11.2", "", { "dependencies": { "@standard-schema/spec": "^1.0.0", "@standard-schema/utils": "^0.3.0", "immer": "^11.0.0", "redux": "^5.0.1", "redux-thunk": "^3.1.0", "reselect": "^5.1.0" }, "peerDependencies": { "react": "^16.9.0 || ^17.0.0 || ^18 || ^19", "react-redux": "^7.2.1 || ^8.1.3 || ^9.0.0" }, "optionalPeers": ["react", "react-redux"] }, "sha512-Kd6kAHTA6/nUpp8mySPqj3en3dm0tdMIgbttnQ1xFMVpufoj+ADi8pXLBsd4xzTRHQa7t/Jv8W5UnCuW4kuWMQ=="],
12251259
1226− "@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.0-beta.27", "", {}, "sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA=="],
1260+ "@rolldown/binding-android-arm64": ["@rolldown/binding-android-arm64@1.0.0-rc.12", "", { "os": "android", "cpu": "arm64" }, "sha512-pv1y2Fv0JybcykuiiD3qBOBdz6RteYojRFY1d+b95WVuzx211CRh+ytI/+9iVyWQ6koTh5dawe4S/yRfOFjgaA=="],
1261+
1262+ "@rolldown/binding-darwin-arm64": ["@rolldown/binding-darwin-arm64@1.0.0-rc.12", "", { "os": "darwin", "cpu": "arm64" }, "sha512-cFYr6zTG/3PXXF3pUO+umXxt1wkRK/0AYT8lDwuqvRC+LuKYWSAQAQZjCWDQpAH172ZV6ieYrNnFzVVcnSflAg=="],
1263+
1264+ "@rolldown/binding-darwin-x64": ["@rolldown/binding-darwin-x64@1.0.0-rc.12", "", { "os": "darwin", "cpu": "x64" }, "sha512-ZCsYknnHzeXYps0lGBz8JrF37GpE9bFVefrlmDrAQhOEi4IOIlcoU1+FwHEtyXGx2VkYAvhu7dyBf75EJQffBw=="],
1265+
1266+ "@rolldown/binding-freebsd-x64": ["@rolldown/binding-freebsd-x64@1.0.0-rc.12", "", { "os": "freebsd", "cpu": "x64" }, "sha512-dMLeprcVsyJsKolRXyoTH3NL6qtsT0Y2xeuEA8WQJquWFXkEC4bcu1rLZZSnZRMtAqwtrF/Ib9Ddtpa/Gkge9Q=="],
1267+
1268+ "@rolldown/binding-linux-arm-gnueabihf": ["@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.12", "", { "os": "linux", "cpu": "arm" }, "sha512-YqWjAgGC/9M1lz3GR1r1rP79nMgo3mQiiA+Hfo+pvKFK1fAJ1bCi0ZQVh8noOqNacuY1qIcfyVfP6HoyBRZ85Q=="],
1269+
1270+ "@rolldown/binding-linux-arm64-gnu": ["@rolldown/binding-linux-arm64-gnu@1.0.0-rc.12", "", { "os": "linux", "cpu": "arm64" }, "sha512-/I5AS4cIroLpslsmzXfwbe5OmWvSsrFuEw3mwvbQ1kDxJ822hFHIx+vsN/TAzNVyepI/j/GSzrtCIwQPeKCLIg=="],
1271+
1272+ "@rolldown/binding-linux-arm64-musl": ["@rolldown/binding-linux-arm64-musl@1.0.0-rc.12", "", { "os": "linux", "cpu": "arm64" }, "sha512-V6/wZztnBqlx5hJQqNWwFdxIKN0m38p8Jas+VoSfgH54HSj9tKTt1dZvG6JRHcjh6D7TvrJPWFGaY9UBVOaWPw=="],
1273+
1274+ "@rolldown/binding-linux-ppc64-gnu": ["@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.12", "", { "os": "linux", "cpu": "ppc64" }, "sha512-AP3E9BpcUYliZCxa3w5Kwj9OtEVDYK6sVoUzy4vTOJsjPOgdaJZKFmN4oOlX0Wp0RPV2ETfmIra9x1xuayFB7g=="],
1275+
1276+ "@rolldown/binding-linux-s390x-gnu": ["@rolldown/binding-linux-s390x-gnu@1.0.0-rc.12", "", { "os": "linux", "cpu": "s390x" }, "sha512-nWwpvUSPkoFmZo0kQazZYOrT7J5DGOJ/+QHHzjvNlooDZED8oH82Yg67HvehPPLAg5fUff7TfWFHQS8IV1n3og=="],
1277+
1278+ "@rolldown/binding-linux-x64-gnu": ["@rolldown/binding-linux-x64-gnu@1.0.0-rc.12", "", { "os": "linux", "cpu": "x64" }, "sha512-RNrafz5bcwRy+O9e6P8Z/OCAJW/A+qtBczIqVYwTs14pf4iV1/+eKEjdOUta93q2TsT/FI0XYDP3TCky38LMAg=="],
1279+
1280+ "@rolldown/binding-linux-x64-musl": ["@rolldown/binding-linux-x64-musl@1.0.0-rc.12", "", { "os": "linux", "cpu": "x64" }, "sha512-Jpw/0iwoKWx3LJ2rc1yjFrj+T7iHZn2JDg1Yny1ma0luviFS4mhAIcd1LFNxK3EYu3DHWCps0ydXQ5i/rrJ2ig=="],
1281+
1282+ "@rolldown/binding-openharmony-arm64": ["@rolldown/binding-openharmony-arm64@1.0.0-rc.12", "", { "os": "none", "cpu": "arm64" }, "sha512-vRugONE4yMfVn0+7lUKdKvN4D5YusEiPilaoO2sgUWpCvrncvWgPMzK00ZFFJuiPgLwgFNP5eSiUlv2tfc+lpA=="],
1283+
1284+ "@rolldown/binding-wasm32-wasi": ["@rolldown/binding-wasm32-wasi@1.0.0-rc.12", "", { "dependencies": { "@napi-rs/wasm-runtime": "^1.1.1" }, "cpu": "none" }, "sha512-ykGiLr/6kkiHc0XnBfmFJuCjr5ZYKKofkx+chJWDjitX+KsJuAmrzWhwyOMSHzPhzOHOy7u9HlFoa5MoAOJ/Zg=="],
1285+
1286+ "@rolldown/binding-win32-arm64-msvc": ["@rolldown/binding-win32-arm64-msvc@1.0.0-rc.12", "", { "os": "win32", "cpu": "arm64" }, "sha512-5eOND4duWkwx1AzCxadcOrNeighiLwMInEADT0YM7xeEOOFcovWZCq8dadXgcRHSf3Ulh1kFo/qvzoFiCLOL1Q=="],
1287+
1288+ "@rolldown/binding-win32-x64-msvc": ["@rolldown/binding-win32-x64-msvc@1.0.0-rc.12", "", { "os": "win32", "cpu": "x64" }, "sha512-PyqoipaswDLAZtot351MLhrlrh6lcZPo2LSYE+VDxbVk24LVKAGOuE4hb8xZQmrPAuEtTZW8E6D2zc5EUZX4Lw=="],
1289+
1290+ "@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.0-rc.7", "", {}, "sha512-qujRfC8sFVInYSPPMLQByRh7zhwkGFS4+tyMQ83srV1qrxL4g8E2tyxVVyxd0+8QeBM1mIk9KbWxkegRr76XzA=="],
12271291
12281292 "@rollup/pluginutils": ["@rollup/pluginutils@5.3.0", "", { "dependencies": { "@types/estree": "^1.0.0", "estree-walker": "^2.0.2", "picomatch": "^4.0.2" }, "peerDependencies": { "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" }, "optionalPeers": ["rollup"] }, "sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q=="],
12291293
@@ -1337,12 +1401,36 @@ · 107 unmodified lines
13371401
13381402 "@tanstack/react-router": ["@tanstack/react-router@1.168.10", "", { "dependencies": { "@tanstack/history": "1.161.6", "@tanstack/react-store": "^0.9.3", "@tanstack/router-core": "1.168.9", "isbot": "^5.1.22" }, "peerDependencies": { "react": ">=18.0.0 || >=19.0.0", "react-dom": ">=18.0.0 || >=19.0.0" } }, "sha512-/RmDlOwDkCug609KdPB3U+U1zmrtadJpvsmRg2zEn8TRCKRNri7dYZIjQZbNg8PgUiRL4T6njrZBV1ChzblNaA=="],
13391403
1404+ "@tanstack/react-start": ["@tanstack/react-start@1.167.16", "", { "dependencies": { "@tanstack/react-router": "1.168.10", "@tanstack/react-start-client": "1.166.25", "@tanstack/react-start-server": "1.166.25", "@tanstack/router-utils": "^1.161.6", "@tanstack/start-client-core": "1.167.9", "@tanstack/start-plugin-core": "1.167.17", "@tanstack/start-server-core": "1.167.9", "pathe": "^2.0.3" }, "peerDependencies": { "react": ">=18.0.0 || >=19.0.0", "react-dom": ">=18.0.0 || >=19.0.0", "vite": ">=7.0.0" }, "bin": { "intent": "bin/intent.js" } }, "sha512-vHIhn+FTWfAVhRus1BZEaBZPhnYL+StDuMlShslIBPEGGTCRt11BxNUfV/iDpr7zbxw36Snj7zGfI7DwfjjlDQ=="],
1405+
1406+ "@tanstack/react-start-client": ["@tanstack/react-start-client@1.166.25", "", { "dependencies": { "@tanstack/react-router": "1.168.10", "@tanstack/router-core": "1.168.9", "@tanstack/start-client-core": "1.167.9" }, "peerDependencies": { "react": ">=18.0.0 || >=19.0.0", "react-dom": ">=18.0.0 || >=19.0.0" } }, "sha512-FvD279zzneUtsfhaTv2c29qhE1Z3wHy3dt3cCjn9LzWZehOgn5Ij78s0YpmQaQ8lSF3YL7CySE3pDk9XHE6YeA=="],
1407+
1408+ "@tanstack/react-start-server": ["@tanstack/react-start-server@1.166.25", "", { "dependencies": { "@tanstack/history": "1.161.6", "@tanstack/react-router": "1.168.10", "@tanstack/router-core": "1.168.9", "@tanstack/start-client-core": "1.167.9", "@tanstack/start-server-core": "1.167.9" }, "peerDependencies": { "react": ">=18.0.0 || >=19.0.0", "react-dom": ">=18.0.0 || >=19.0.0" } }, "sha512-bPLADxlplvcnAcnZvBjJl2MzgUnB85d7Mu5aEkYoOFxhz0WiG6mZp7BDadIJuCd33NYMirsd3XrjfCHNzrMTyg=="],
1409+
13401410 "@tanstack/react-store": ["@tanstack/react-store@0.9.3", "", { "dependencies": { "@tanstack/store": "0.9.3", "use-sync-external-store": "^1.6.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-y2iHd/N9OkoQbFJLUX1T9vbc2O9tjH0pQRgTcx1/Nz4IlwLvkgpuglXUx+mXt0g5ZDFrEeDnONPqkbfxXJKwRg=="],
13411411
13421412 "@tanstack/router-core": ["@tanstack/router-core@1.168.9", "", { "dependencies": { "@tanstack/history": "1.161.6", "cookie-es": "^2.0.0", "seroval": "^1.4.2", "seroval-plugins": "^1.4.2" }, "bin": { "intent": "bin/intent.js" } }, "sha512-18oeEwEDyXOIuO1VBP9ACaK7tYHZUjynGDCoUh/5c/BNhia9vCJCp9O0LfhZXOorDc/PmLSgvmweFhVmIxF10g=="],
13431413
1414+ "@tanstack/router-generator": ["@tanstack/router-generator@1.166.24", "", { "dependencies": { "@tanstack/router-core": "1.168.9", "@tanstack/router-utils": "1.161.6", "@tanstack/virtual-file-routes": "1.161.7", "prettier": "^3.5.0", "recast": "^0.23.11", "source-map": "^0.7.4", "tsx": "^4.19.2", "zod": "^3.24.2" } }, "sha512-vdaGKwuH+r+DPe6R1mjk+TDDmDH6NTG7QqwxHqGEvOH4aGf9sPjhmRKNJZqQr8cPIbfp6u5lXyZ1TeDcSNMVEA=="],
1415+
1416+ "@tanstack/router-plugin": ["@tanstack/router-plugin@1.167.12", "", { "dependencies": { "@babel/core": "^7.28.5", "@babel/plugin-syntax-jsx": "^7.27.1", "@babel/plugin-syntax-typescript": "^7.27.1", "@babel/template": "^7.27.2", "@babel/traverse": "^7.28.5", "@babel/types": "^7.28.5", "@tanstack/router-core": "1.168.9", "@tanstack/router-generator": "1.166.24", "@tanstack/router-utils": "1.161.6", "@tanstack/virtual-file-routes": "1.161.7", "chokidar": "^3.6.0", "unplugin": "^2.1.2", "zod": "^3.24.2" }, "peerDependencies": { "@rsbuild/core": ">=1.0.2", "@tanstack/react-router": "^1.168.10", "vite": ">=5.0.0 || >=6.0.0 || >=7.0.0", "vite-plugin-solid": "^2.11.10", "webpack": ">=5.92.0" }, "optionalPeers": ["@rsbuild/core", "@tanstack/react-router", "vite", "vite-plugin-solid", "webpack"], "bin": { "intent": "bin/intent.js" } }, "sha512-StEHcctCuFI5taSjO+lhR/yQ+EK63BdyYa+ne6FoNQPB3MMrOUrz2ZVnbqILRLkh2b+p2EfBKt65sgAKdKygPQ=="],
1417+
1418+ "@tanstack/router-utils": ["@tanstack/router-utils@1.161.6", "", { "dependencies": { "@babel/core": "^7.28.5", "@babel/generator": "^7.28.5", "@babel/parser": "^7.28.5", "@babel/types": "^7.28.5", "ansis": "^4.1.0", "babel-dead-code-elimination": "^1.0.12", "diff": "^8.0.2", "pathe": "^2.0.3", "tinyglobby": "^0.2.15" } }, "sha512-nRcYw+w2OEgK6VfjirYvGyPLOK+tZQz1jkYcmH5AjMamQ9PycnlxZF2aEZtPpNoUsaceX2bHptn6Ub5hGXqNvw=="],
1419+
1420+ "@tanstack/start-client-core": ["@tanstack/start-client-core@1.167.9", "", { "dependencies": { "@tanstack/router-core": "1.168.9", "@tanstack/start-fn-stubs": "1.161.6", "@tanstack/start-storage-context": "1.166.23", "seroval": "^1.4.2" }, "bin": { "intent": "bin/intent.js" } }, "sha512-2ETQO/bxiZGsoTdPxZb7xR8YqCy5l4kv/QPkwIXuvx/A4BjufngXfgISjXUicXsFRIBZeiFnBzp9A38UMsS2iA=="],
1421+
1422+ "@tanstack/start-fn-stubs": ["@tanstack/start-fn-stubs@1.161.6", "", {}, "sha512-Y6QSlGiLga8cHfvxGGaonXIlt2bIUTVdH6AMjmpMp7+ANNCp+N96GQbjjhLye3JkaxDfP68x5iZA8NK4imgRig=="],
1423+
1424+ "@tanstack/start-plugin-core": ["@tanstack/start-plugin-core@1.167.17", "", { "dependencies": { "@babel/code-frame": "7.27.1", "@babel/core": "^7.28.5", "@babel/types": "^7.28.5", "@rolldown/pluginutils": "1.0.0-beta.40", "@tanstack/router-core": "1.168.9", "@tanstack/router-generator": "1.166.24", "@tanstack/router-plugin": "1.167.12", "@tanstack/router-utils": "1.161.6", "@tanstack/start-client-core": "1.167.9", "@tanstack/start-server-core": "1.167.9", "cheerio": "^1.0.0", "exsolve": "^1.0.7", "pathe": "^2.0.3", "picomatch": "^4.0.3", "source-map": "^0.7.6", "srvx": "^0.11.9", "tinyglobby": "^0.2.15", "ufo": "^1.5.4", "vitefu": "^1.1.1", "xmlbuilder2": "^4.0.3", "zod": "^3.24.2" }, "peerDependencies": { "vite": ">=7.0.0" } }, "sha512-OkorpOobGOEDVr72QUmkzKjbawKC05CSz+1B3OObB/AxBIIw+lLLhTXbV45QkX2LZA7dcRvPJYZGOH1pkFqA1g=="],
1425+
1426+ "@tanstack/start-server-core": ["@tanstack/start-server-core@1.167.9", "", { "dependencies": { "@tanstack/history": "1.161.6", "@tanstack/router-core": "1.168.9", "@tanstack/start-client-core": "1.167.9", "@tanstack/start-storage-context": "1.166.23", "h3-v2": "npm:h3@2.0.1-rc.16", "seroval": "^1.4.2" }, "bin": { "intent": "bin/intent.js" } }, "sha512-vKkslQIihoDDVumF73VXT7PVFmN7Nea0nKhZx7gMbc0m09yPQYYR1dn86/dz14k6/7cDkJ+qKXa09rlVlN/i9Q=="],
1427+
1428+ "@tanstack/start-storage-context": ["@tanstack/start-storage-context@1.166.23", "", { "dependencies": { "@tanstack/router-core": "1.168.9" } }, "sha512-3vEdiYRMx+r+Q7Xqxj3YmADPIpMm7fkKxDa8ITwodGXiw+SBJCGkpBXGUWjOXyXkIyqGHKM5UrReTcVUTkmaug=="],
1429+
13441430 "@tanstack/store": ["@tanstack/store@0.9.3", "", {}, "sha512-8reSzl/qGWGGVKhBoxXPMWzATSbZLZFWhwBAFO9NAyp0TxzfBP0mIrGb8CP8KrQTmvzXlR/vFPPUrHTLBGyFyw=="],
13451431
1432+ "@tanstack/virtual-file-routes": ["@tanstack/virtual-file-routes@1.161.7", "", { "bin": { "intent": "bin/intent.js" } }, "sha512-olW33+Cn+bsCsZKPwEGhlkqS6w3M2slFv11JIobdnCFKMLG97oAI2kWKdx5/zsywTL8flpnoIgaZZPlQTFYhdQ=="],
1433+
13461434 "@turbo/darwin-64": ["@turbo/darwin-64@2.9.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-yg0qdthTUuV/K0oJB9t8YGweW1hOefQ+NTiSA6gw/mwAqqifCvAXH/kDkvVj/fFP9+wzoQ4WjyAF5/syDbCIHA=="],
13471435
13481436 "@turbo/darwin-arm64": ["@turbo/darwin-arm64@2.9.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-x4H9U8cXZob3oqTleKOEdY89OCWwLX3qVRpW0NeZg+CHDXemYD+PhACjwjvh7orIlhmmq2Lk+7iO7b34kphFig=="],
@@ -1355,15 +1443,9 @@ · 6 unmodified lines
13551443
13561444 "@turbo/windows-arm64": ["@turbo/windows-arm64@2.9.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-qPFjErR4MrKo71lNfqgUNaajftZN2nyaOsSxMSb2NI+5r/zlB26yjXUKYvADGg4EWvaLTJPIzgZDT9ZX+WN9bw=="],
13571445
1358− "@types/accepts": ["@types/accepts@1.3.7", "", { "dependencies": { "@types/node": "*" } }, "sha512-Pay9fq2lM2wXPWbteBsRAGiWH2hig4ZE2asK+mm7kUzlxRTfL961rj89I6zV/E3PcIkDqyuBEcMxFT7rccugeQ=="],
1359−
1360− "@types/babel__core": ["@types/babel__core@7.20.5", "", { "dependencies": { "@babel/parser": "^7.20.7", "@babel/types": "^7.20.7", "@types/babel__generator": "*", "@types/babel__template": "*", "@types/babel__traverse": "*" } }, "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA=="],
1361−
1362− "@types/babel__generator": ["@types/babel__generator@7.27.0", "", { "dependencies": { "@babel/types": "^7.0.0" } }, "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg=="],
1446+ "@tybys/wasm-util": ["@tybys/wasm-util@0.10.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg=="],
13631447
1364− "@types/babel__template": ["@types/babel__template@7.4.4", "", { "dependencies": { "@babel/parser": "^7.1.0", "@babel/types": "^7.0.0" } }, "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A=="],
1365−
1366− "@types/babel__traverse": ["@types/babel__traverse@7.28.0", "", { "dependencies": { "@babel/types": "^7.28.2" } }, "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q=="],
1448+ "@types/accepts": ["@types/accepts@1.3.7", "", { "dependencies": { "@types/node": "*" } }, "sha512-Pay9fq2lM2wXPWbteBsRAGiWH2hig4ZE2asK+mm7kUzlxRTfL961rj89I6zV/E3PcIkDqyuBEcMxFT7rccugeQ=="],
13671449
13681450 "@types/body-parser": ["@types/body-parser@1.19.6", "", { "dependencies": { "@types/connect": "*", "@types/node": "*" } }, "sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g=="],
13691451
@@ -1527,7 +1609,7 @@ · 157 unmodified lines
15271609
15281610 "@vercel/routing-utils": ["@vercel/routing-utils@5.3.3", "", { "dependencies": { "path-to-regexp": "6.1.0", "path-to-regexp-updated": "npm:path-to-regexp@6.3.0" }, "optionalDependencies": { "ajv": "^6.12.3" } }, "sha512-KYm2sLNUD48gDScv8ob4ejc3Gww2jcJyW80hTdYlenAPz/5BQar1Gyh38xrUuZ532TUwSb5mV1uRbAuiykq0EQ=="],
15291611
1530− "@vitejs/plugin-react": ["@vitejs/plugin-react@4.7.0", "", { "dependencies": { "@babel/core": "^7.28.0", "@babel/plugin-transform-react-jsx-self": "^7.27.1", "@babel/plugin-transform-react-jsx-source": "^7.27.1", "@rolldown/pluginutils": "1.0.0-beta.27", "@types/babel__core": "^7.20.5", "react-refresh": "^0.17.0" }, "peerDependencies": { "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" } }, "sha512-gUu9hwfWvvEDBBmgtAowQCojwZmJ5mcLn3aufeCsitijs3+f2NsrPtlAWIR6OPiqljl96GVCUbLe0HyqIpVaoA=="],
1612+ "@vitejs/plugin-react": ["@vitejs/plugin-react@6.0.1", "", { "dependencies": { "@rolldown/pluginutils": "1.0.0-rc.7" }, "peerDependencies": { "@rolldown/plugin-babel": "^0.1.7 || ^0.2.0", "babel-plugin-react-compiler": "^1.0.0", "vite": "^8.0.0" }, "optionalPeers": ["@rolldown/plugin-babel", "babel-plugin-react-compiler"] }, "sha512-l9X/E3cDb+xY3SWzlG1MOGt2usfEHGMNIaegaUGFsLkb3RCn/k8/TOXBcab+OndDI4TBtktT8/9BwwW8Vi9KUQ=="],
15311613
15321614 "@vitest/expect": ["@vitest/expect@3.2.4", "", { "dependencies": { "@types/chai": "^5.2.2", "@vitest/spy": "3.2.4", "@vitest/utils": "3.2.4", "chai": "^5.2.0", "tinyrainbow": "^2.0.0" } }, "sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig=="],
15331615
@@ -1571,6 +1653,8 @@ · 37 unmodified lines
15711653
15721654 "ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="],
15731655
1656+ "ansis": ["ansis@4.2.0", "", {}, "sha512-HqZ5rWlFjGiV0tDm3UxxgNRqsOTniqoKZu0pIAfh7TZQMGuZK+hH0drySty0si0QXj1ieop4+SkSfPZBPPkHig=="],
1657+
15741658 "anymatch": ["anymatch@3.1.3", "", { "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" } }, "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw=="],
15751659
15761660 "app-builder-bin": ["app-builder-bin@5.0.0-alpha.12", "", {}, "sha512-j87o0j6LqPL3QRr8yid6c+Tt5gC7xNfYo6uQIQkorAC6MpeayVMZrEDzKmJJ/Hlv7EnOQpaRm53k6ktDYZyB6w=="],
@@ -1593,6 +1677,8 @@ · 16 unmodified lines
15931677
15941678 "assertion-error": ["assertion-error@2.0.1", "", {}, "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA=="],
15951679
1680+ "ast-types": ["ast-types@0.16.1", "", { "dependencies": { "tslib": "^2.0.1" } }, "sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg=="],
1681+
15961682 "astral-regex": ["astral-regex@2.0.0", "", {}, "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ=="],
15971683
15981684 "astro": ["astro@6.1.3", "", { "dependencies": { "@astrojs/compiler": "^3.0.1", "@astrojs/internal-helpers": "0.8.0", "@astrojs/markdown-remark": "7.1.0", "@astrojs/telemetry": "3.3.0", "@capsizecss/unpack": "^4.0.0", "@clack/prompts": "^1.1.0", "@oslojs/encoding": "^1.1.0", "@rollup/pluginutils": "^5.3.0", "aria-query": "^5.3.2", "axobject-query": "^4.1.0", "ci-info": "^4.4.0", "clsx": "^2.1.1", "common-ancestor-path": "^2.0.0", "cookie": "^1.1.1", "devalue": "^5.6.3", "diff": "^8.0.3", "dlv": "^1.1.3", "dset": "^3.1.4", "es-module-lexer": "^2.0.0", "esbuild": "^0.27.3", "flattie": "^1.1.1", "fontace": "~0.4.1", "github-slugger": "^2.0.0", "html-escaper": "3.0.3", "http-cache-semantics": "^4.2.0", "js-yaml": "^4.1.1", "magic-string": "^0.30.21", "magicast": "^0.5.2", "mrmime": "^2.0.1", "neotraverse": "^0.6.18", "obug": "^2.1.1", "p-limit": "^7.3.0", "p-queue": "^9.1.0", "package-manager-detector": "^1.6.0", "piccolore": "^0.1.3", "picomatch": "^4.0.3", "rehype": "^13.0.2", "semver": "^7.7.4", "shiki": "^4.0.2", "smol-toml": "^1.6.0", "svgo": "^4.0.1", "tinyclip": "^0.1.12", "tinyexec": "^1.0.4", "tinyglobby": "^0.2.15", "tsconfck": "^3.1.6", "ultrahtml": "^1.6.0", "unifont": "~0.7.4", "unist-util-visit": "^5.1.0", "unstorage": "^1.17.4", "vfile": "^6.0.3", "vite": "^7.3.1", "vitefu": "^1.1.2", "xxhash-wasm": "^1.1.0", "yargs-parser": "^22.0.0", "zod": "^4.3.6" }, "optionalDependencies": { "sharp": "^0.34.0" }, "bin": { "astro": "bin/astro.mjs" } }, "sha512-FUKbBYOdYYrRNZwDd9I5CVSfR6Nj9aZeNzcjcvh1FgHwR0uXawkYFR3HiGxmdmAB2m8fs0iIkDdsiUfwGeO8qA=="],
@@ -1611,6 +1697,8 @@ · 12 unmodified lines
16111697
16121698 "axobject-query": ["axobject-query@4.1.0", "", {}, "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ=="],
16131699
1700+ "babel-dead-code-elimination": ["babel-dead-code-elimination@1.0.12", "", { "dependencies": { "@babel/core": "^7.23.7", "@babel/parser": "^7.23.6", "@babel/traverse": "^7.23.7", "@babel/types": "^7.23.6" } }, "sha512-GERT7L2TiYcYDtYk1IpD+ASAYXjKbLTDPhBtYj7X1NuRMDTMtAx9kyBenub1Ev41lo91OHCKdmP+egTDmfQ7Ig=="],
1701+
16141702 "bail": ["bail@2.0.2", "", {}, "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw=="],
16151703
16161704 "balanced-match": ["balanced-match@4.0.4", "", {}, "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="],
@@ -1623,6 +1711,8 @@ · 6 unmodified lines
16231711
16241712 "better-sqlite3": ["better-sqlite3@12.8.0", "", { "dependencies": { "bindings": "^1.5.0", "prebuild-install": "^7.1.1" } }, "sha512-RxD2Vd96sQDjQr20kdP+F+dK/1OUNiVOl200vKBZY8u0vTwysfolF6Hq+3ZK2+h8My9YvZhHsF+RSGZW2VYrPQ=="],
16251713
1714+ "binary-extensions": ["binary-extensions@2.3.0", "", {}, "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw=="],
1715+
16261716 "bindings": ["bindings@1.5.0", "", { "dependencies": { "file-uri-to-path": "1.0.0" } }, "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ=="],
16271717
16281718 "bl": ["bl@4.1.0", "", { "dependencies": { "buffer": "^5.5.0", "inherits": "^2.0.4", "readable-stream": "^3.4.0" } }, "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w=="],
@@ -1687,6 +1777,10 @@ · 58 unmodified lines
16871777
16881778 "check-error": ["check-error@2.1.3", "", {}, "sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA=="],
16891779
1780+ "cheerio": ["cheerio@1.2.0", "", { "dependencies": { "cheerio-select": "^2.1.0", "dom-serializer": "^2.0.0", "domhandler": "^5.0.3", "domutils": "^3.2.2", "encoding-sniffer": "^0.2.1", "htmlparser2": "^10.1.0", "parse5": "^7.3.0", "parse5-htmlparser2-tree-adapter": "^7.1.0", "parse5-parser-stream": "^7.1.2", "undici": "^7.19.0", "whatwg-mimetype": "^4.0.0" } }, "sha512-WDrybc/gKFpTYQutKIK6UvfcuxijIZfMfXaYm8NMsPQxSYvf+13fXUJ4rztGGbJcBQ/GF55gvrZ0Bc0bj/mqvg=="],
1781+
1782+ "cheerio-select": ["cheerio-select@2.1.0", "", { "dependencies": { "boolbase": "^1.0.0", "css-select": "^5.1.0", "css-what": "^6.1.0", "domelementtype": "^2.3.0", "domhandler": "^5.0.3", "domutils": "^3.0.1" } }, "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g=="],
1783+
16901784 "chevrotain": ["chevrotain@11.1.2", "", { "dependencies": { "@chevrotain/cst-dts-gen": "11.1.2", "@chevrotain/gast": "11.1.2", "@chevrotain/regexp-to-ast": "11.1.2", "@chevrotain/types": "11.1.2", "@chevrotain/utils": "11.1.2", "lodash-es": "4.17.23" } }, "sha512-opLQzEVriiH1uUQ4Kctsd49bRoFDXGGSC4GUqj7pGyxM3RehRhvTlZJc1FL/Flew2p5uwxa1tUDWKzI4wNM8pg=="],
16911785
16921786 "chevrotain-allstar": ["chevrotain-allstar@0.3.1", "", { "dependencies": { "lodash-es": "^4.17.21" }, "peerDependencies": { "chevrotain": "^11.0.0" } }, "sha512-b7g+y9A0v4mxCW1qUhf3BSVPg+/NvGErk/dOkrDaHA0nQIQGAtrOjlX//9OQtRlSCy+x9rfB5N8yC71lH1nvMw=="],
@@ -1961,13 +2055,15 @@ · 268 unmodified lines
19612055
19622056 "encoding": ["encoding@0.1.13", "", { "dependencies": { "iconv-lite": "^0.6.2" } }, "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A=="],
19632057
2058+ "encoding-sniffer": ["encoding-sniffer@0.2.1", "", { "dependencies": { "iconv-lite": "^0.6.3", "whatwg-encoding": "^3.1.1" } }, "sha512-5gvq20T6vfpekVtqrYQsSCFZ1wEg5+wW0/QaZMWkFr6BqD3NfKs0rLCx4rrVlSWJeZb5NBJgVLswK/w2MWU+Gw=="],
2059+
19642060 "end-of-stream": ["end-of-stream@1.4.5", "", { "dependencies": { "once": "^1.4.0" } }, "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg=="],
19652061
19662062 "enhanced-resolve": ["enhanced-resolve@5.20.1", "", { "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.3.0" } }, "sha512-Qohcme7V1inbAfvjItgw0EaxVX5q2rdVEZHRBrEQdRZTssLDGsL8Lwrznl8oQ/6kuTJONLaDcGjkNP247XEhcA=="],
19672063
19682064 "enquirer": ["enquirer@2.4.1", "", { "dependencies": { "ansi-colors": "^4.1.1", "strip-ansi": "^6.0.1" } }, "sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ=="],
19692065
1970− "entities": ["entities@6.0.1", "", {}, "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g=="],
2066+ "entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="],
19712067
19722068 "env-paths": ["env-paths@2.2.1", "", {}, "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A=="],
19732069
@@ -2021,6 +2117,8 @@ · 47 unmodified lines
20212117
20222118 "express-rate-limit": ["express-rate-limit@8.3.2", "", { "dependencies": { "ip-address": "10.1.0" }, "peerDependencies": { "express": ">= 4.11" } }, "sha512-77VmFeJkO0/rvimEDuUC5H30oqUC4EyOhyGccfqoLebB0oiEYfM7nwPrsDsBL1gsTpwfzX8SFy2MT3TDyRq+bg=="],
20232119
2120+ "exsolve": ["exsolve@1.0.8", "", {}, "sha512-LmDxfWXwcTArk8fUEnOfSZpHOJ6zOMUJKOtFLFqJLoKJetuQG874Uc7/Kki7zFLzYybmZhp1M7+98pfMqeX8yA=="],
2121+
20242122 "extend": ["extend@3.0.2", "", {}, "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="],
20252123
20262124 "extendable-error": ["extendable-error@0.1.7", "", {}, "sha512-UOiS2in6/Q0FK0R0q6UY9vYpQ21mr/Qn1KOnte7vsACuNJf514WvCCUHSRCPcgjPT2bAhNIJdlE6bVap1GKmeg=="],
@@ -2127,6 +2225,8 @@ · 100 unmodified lines
21272225
21282226 "h3": ["h3@1.15.11", "", { "dependencies": { "cookie-es": "^1.2.3", "crossws": "^0.3.5", "defu": "^6.1.6", "destr": "^2.0.5", "iron-webcrypto": "^1.2.1", "node-mock-http": "^1.0.4", "radix3": "^1.1.2", "ufo": "^1.6.3", "uncrypto": "^0.1.3" } }, "sha512-L3THSe2MPeBwgIZVSH5zLdBBU90TOxarvhK9d04IDY2AmVS8j2Jz2LIWtwsGOU3lu2I5jCN7FNvVfY2+XyF+mg=="],
21292227
2228+ "h3-v2": ["h3@2.0.1-rc.16", "", { "dependencies": { "rou3": "^0.8.0", "srvx": "^0.11.9" }, "peerDependencies": { "crossws": "^0.4.1" }, "optionalPeers": ["crossws"], "bin": { "h3": "bin/h3.mjs" } }, "sha512-h+pjvyujdo9way8qj6FUbhaQcHlR8FEq65EhTX9ViT5pK8aLj68uFl4hBkF+hsTJAH+H1END2Yv6hTIsabGfag=="],
2229+
21302230 "hachure-fill": ["hachure-fill@0.5.2", "", {}, "sha512-3GKBOn+m2LX9iq+JC1064cSFprJY4jL1jCXTcpnfER5HYE2l/4EfWSGzkPa/ZDBmYI0ZOEj5VHV/eKnPGkHuOg=="],
21312231
21322232 "has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="],
@@ -2173,6 +2273,8 @@ · 40 unmodified lines
21732273
21742274 "html-void-elements": ["html-void-elements@3.0.0", "", {}, "sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg=="],
21752275
2276+ "htmlparser2": ["htmlparser2@10.1.0", "", { "dependencies": { "domelementtype": "^2.3.0", "domhandler": "^5.0.3", "domutils": "^3.2.2", "entities": "^7.0.1" } }, "sha512-VTZkM9GWRAtEpveh7MSF6SjjrpNVNNVJfFup7xTY3UpFtm67foy9HDVXneLtFVt4pMz5kZtgNcvCniNFb1hlEQ=="],
2277+
21762278 "http-cache-semantics": ["http-cache-semantics@4.2.0", "", {}, "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ=="],
21772279
21782280 "http-errors": ["http-errors@2.0.1", "", { "dependencies": { "depd": "~2.0.0", "inherits": "~2.0.4", "setprototypeof": "~1.2.0", "statuses": "~2.0.2", "toidentifier": "~1.0.1" } }, "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ=="],
@@ -2221,6 +2323,8 @@ · 42 unmodified lines
22212323
22222324 "is-alphanumerical": ["is-alphanumerical@2.0.1", "", { "dependencies": { "is-alphabetical": "^2.0.0", "is-decimal": "^2.0.0" } }, "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw=="],
22232325
2326+ "is-binary-path": ["is-binary-path@2.1.0", "", { "dependencies": { "binary-extensions": "^2.0.0" } }, "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw=="],
2327+
22242328 "is-decimal": ["is-decimal@2.0.1", "", {}, "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A=="],
22252329
22262330 "is-docker": ["is-docker@3.0.0", "", { "bin": { "is-docker": "cli.js" } }, "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ=="],
@@ -2605,6 +2709,10 @@ · 378 unmodified lines
26052709
26062710 "parse5": ["parse5@7.3.0", "", { "dependencies": { "entities": "^6.0.0" } }, "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw=="],
26072711
2712+ "parse5-htmlparser2-tree-adapter": ["parse5-htmlparser2-tree-adapter@7.1.0", "", { "dependencies": { "domhandler": "^5.0.3", "parse5": "^7.0.0" } }, "sha512-ruw5xyKs6lrpo9x9rCZqZZnIUntICjQAd0Wsmp396Ul9lN/h+ifgVV1x1gZHi8euej6wTfpqX8j+BFQxF0NS/g=="],
2713+
2714+ "parse5-parser-stream": ["parse5-parser-stream@7.1.2", "", { "dependencies": { "parse5": "^7.0.0" } }, "sha512-JyeQc9iwFLn5TbvvqACIF/VXG6abODeB3Fwmv/TGdLk2LfbWkaySGY72at4+Ty7EkPZj854u4CrICqNk2qIbow=="],
2715+
26082716 "parseurl": ["parseurl@1.3.3", "", {}, "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="],
26092717
26102718 "path-data-parser": ["path-data-parser@0.1.0", "", {}, "sha512-NOnmBpt5Y2RWbuv0LMzsayp3lVylAHLPUTut412ZA3l+C4uw4ZVkQbjShYCQ8TCpUMdPapr4YjUqLYD6v68j+w=="],
@@ -2747,8 +2855,6 @@ · 136 unmodified lines
27472855
27482856 "react-redux": ["react-redux@9.2.0", "", { "dependencies": { "@types/use-sync-external-store": "^0.0.6", "use-sync-external-store": "^1.4.0" }, "peerDependencies": { "@types/react": "^18.2.25 || ^19", "react": "^18.0 || ^19", "redux": "^5.0.0" }, "optionalPeers": ["@types/react", "redux"] }, "sha512-ROY9fvHhwOD9ySfrF0wmvu//bKCQ6AeZZq1nJNtbDC+kk5DuSuNX/n6YWYF/SYy7bSba4D4FSz8DJeKY/S/r+g=="],
27492857
2750− "react-refresh": ["react-refresh@0.17.0", "", {}, "sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ=="],
2751−
27522858 "react-remove-scroll": ["react-remove-scroll@2.7.2", "", { "dependencies": { "react-remove-scroll-bar": "^2.3.7", "react-style-singleton": "^2.2.3", "tslib": "^2.1.0", "use-callback-ref": "^1.3.3", "use-sidecar": "^1.1.3" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Iqb9NjCCTt6Hf+vOdNIZGdTiH1QSqr27H/Ek9sv/a97gfueI/5h1s3yRi1nngzMUaOOToin5dI1dXKdXiF+u0Q=="],
27532859
27542860 "react-remove-scroll-bar": ["react-remove-scroll-bar@2.3.8", "", { "dependencies": { "react-style-singleton": "^2.2.2", "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" }, "optionalPeers": ["@types/react"] }, "sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q=="],
@@ -2765,6 +2871,8 @@ · 10 unmodified lines
27652871
27662872 "readdirp": ["readdirp@5.0.0", "", {}, "sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ=="],
27672873
2874+ "recast": ["recast@0.23.11", "", { "dependencies": { "ast-types": "^0.16.1", "esprima": "~4.0.0", "source-map": "~0.6.1", "tiny-invariant": "^1.3.3", "tslib": "^2.0.1" } }, "sha512-YTUo+Flmw4ZXiWfQKGcwwc11KnoRAYgzAE2E7mXKCjSviTKShtxBsN6YUUBB2gtaBzKzeKunxhUwNHQuRryhWA=="],
2875+
27682876 "recharts": ["recharts@3.8.0", "", { "dependencies": { "@reduxjs/toolkit": "^1.9.0 || 2.x.x", "clsx": "^2.1.1", "decimal.js-light": "^2.5.1", "es-toolkit": "^1.39.3", "eventemitter3": "^5.0.1", "immer": "^10.1.1", "react-redux": "8.x.x || 9.x.x", "reselect": "5.1.1", "tiny-invariant": "^1.3.3", "use-sync-external-store": "^1.2.2", "victory-vendor": "^37.0.2" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-is": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-Z/m38DX3L73ExO4Tpc9/iZWHmHnlzWG4njQbxsF5aSjwqmHNDDIm0rdEBArkwsBvR8U6EirlEHiQNYWCVh9sGQ=="],
27692877
27702878 "redux": ["redux@5.0.1", "", {}, "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w=="],
@@ -2837,8 +2945,12 @@ · 66 unmodified lines
28372945
28382946 "robust-predicates": ["robust-predicates@3.0.3", "", {}, "sha512-NS3levdsRIUOmiJ8FZWCP7LG3QpJyrs/TE0Zpf1yvZu8cAJJ6QMW92H1c7kWpdIHo8RvmLxN/o2JXTKHp74lUA=="],
28392947
2948+ "rolldown": ["rolldown@1.0.0-rc.12", "", { "dependencies": { "@oxc-project/types": "=0.122.0", "@rolldown/pluginutils": "1.0.0-rc.12" }, "optionalDependencies": { "@rolldown/binding-android-arm64": "1.0.0-rc.12", "@rolldown/binding-darwin-arm64": "1.0.0-rc.12", "@rolldown/binding-darwin-x64": "1.0.0-rc.12", "@rolldown/binding-freebsd-x64": "1.0.0-rc.12", "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-rc.12", "@rolldown/binding-linux-arm64-gnu": "1.0.0-rc.12", "@rolldown/binding-linux-arm64-musl": "1.0.0-rc.12", "@rolldown/binding-linux-ppc64-gnu": "1.0.0-rc.12", "@rolldown/binding-linux-s390x-gnu": "1.0.0-rc.12", "@rolldown/binding-linux-x64-gnu": "1.0.0-rc.12", "@rolldown/binding-linux-x64-musl": "1.0.0-rc.12", "@rolldown/binding-openharmony-arm64": "1.0.0-rc.12", "@rolldown/binding-wasm32-wasi": "1.0.0-rc.12", "@rolldown/binding-win32-arm64-msvc": "1.0.0-rc.12", "@rolldown/binding-win32-x64-msvc": "1.0.0-rc.12" }, "bin": { "rolldown": "bin/cli.mjs" } }, "sha512-yP4USLIMYrwpPHEFB5JGH1uxhcslv6/hL0OyvTuY+3qlOSJvZ7ntYnoWpehBxufkgN0cvXxppuTu5hHa/zPh+A=="],
2949+
28402950 "rollup": ["rollup@4.60.1", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.60.1", "@rollup/rollup-android-arm64": "4.60.1", "@rollup/rollup-darwin-arm64": "4.60.1", "@rollup/rollup-darwin-x64": "4.60.1", "@rollup/rollup-freebsd-arm64": "4.60.1", "@rollup/rollup-freebsd-x64": "4.60.1", "@rollup/rollup-linux-arm-gnueabihf": "4.60.1", "@rollup/rollup-linux-arm-musleabihf": "4.60.1", "@rollup/rollup-linux-arm64-gnu": "4.60.1", "@rollup/rollup-linux-arm64-musl": "4.60.1", "@rollup/rollup-linux-loong64-gnu": "4.60.1", "@rollup/rollup-linux-loong64-musl": "4.60.1", "@rollup/rollup-linux-ppc64-gnu": "4.60.1", "@rollup/rollup-linux-ppc64-musl": "4.60.1", "@rollup/rollup-linux-riscv64-gnu": "4.60.1", "@rollup/rollup-linux-riscv64-musl": "4.60.1", "@rollup/rollup-linux-s390x-gnu": "4.60.1", "@rollup/rollup-linux-x64-gnu": "4.60.1", "@rollup/rollup-linux-x64-musl": "4.60.1", "@rollup/rollup-openbsd-x64": "4.60.1", "@rollup/rollup-openharmony-arm64": "4.60.1", "@rollup/rollup-win32-arm64-msvc": "4.60.1", "@rollup/rollup-win32-ia32-msvc": "4.60.1", "@rollup/rollup-win32-x64-gnu": "4.60.1", "@rollup/rollup-win32-x64-msvc": "4.60.1", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-VmtB2rFU/GroZ4oL8+ZqXgSA38O6GR8KSIvWmEFv63pQ0G6KaBH9s07PO8XTXP4vI+3UJUEypOfjkGfmSBBR0w=="],
28412951
2952+ "rou3": ["rou3@0.8.1", "", {}, "sha512-ePa+XGk00/3HuCqrEnK3LxJW7I0SdNg6EFzKUJG73hMAdDcOUC/i/aSz7LSDwLrGr33kal/rqOGydzwl6U7zBA=="],
2953+
28422954 "roughjs": ["roughjs@4.6.6", "", { "dependencies": { "hachure-fill": "^0.5.2", "path-data-parser": "^0.1.0", "points-on-curve": "^0.2.0", "points-on-path": "^0.2.1" } }, "sha512-ZUz/69+SYpFN/g/lUlo2FXcIjRkSu3nDarreVdGGndHEBJ6cXPdKguS8JGxwj5HA5xIbVKSmLgr5b3AWxtRfvQ=="],
28432955
28442956 "router": ["router@2.2.0", "", { "dependencies": { "debug": "^4.4.0", "depd": "^2.0.0", "is-promise": "^4.0.0", "parseurl": "^1.3.3", "path-to-regexp": "^8.0.0" } }, "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ=="],
@@ -2915,7 +3027,7 @@ · 70 unmodified lines
29153027
29163028 "sonner": ["sonner@2.0.7", "", { "peerDependencies": { "react": "^18.0.0 || ^19.0.0 || ^19.0.0-rc", "react-dom": "^18.0.0 || ^19.0.0 || ^19.0.0-rc" } }, "sha512-W6ZN4p58k8aDKA4XPcx2hpIQXBRAgyiWVkYhT7CvK6D3iAu7xjvVyhQHg2/iaKJZ1XVJ4r7XuwGL+WGEK37i9w=="],
29173029
2918− "source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="],
3030+ "source-map": ["source-map@0.7.6", "", {}, "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ=="],
29193031
29203032 "source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="],
29213033
@@ -2929,6 +3041,8 @@ · 7 unmodified lines
29293041
29303042 "sprintf-js": ["sprintf-js@1.1.3", "", {}, "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA=="],
29313043
3044+ "srvx": ["srvx@0.11.15", "", { "bin": { "srvx": "bin/srvx.mjs" } }, "sha512-iXsux0UcOjdvs0LCMa2Ws3WwcDUozA3JN3BquNXkaFPP7TpRqgunKdEgoZ/uwb1J6xaYHfxtz9Twlh6yzwM6Tg=="],
3045+
29323046 "ssri": ["ssri@12.0.0", "", { "dependencies": { "minipass": "^7.0.3" } }, "sha512-S7iGNosepx9RadX82oimUkvr0Ct7IjJbEbs4mJcTxst8um95J3sDYU1RBEOvdu6oL1Wek2ODI5i4MAw+dZ6cAQ=="],
29333047
29343048 "stackback": ["stackback@0.0.2", "", {}, "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw=="],
@@ -3087,6 +3201,8 @@ · 152 unmodified lines
30873201
30883202 "unpipe": ["unpipe@1.0.0", "", {}, "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ=="],
30893203
3204+ "unplugin": ["unplugin@2.3.11", "", { "dependencies": { "@jridgewell/remapping": "^2.3.5", "acorn": "^8.15.0", "picomatch": "^4.0.3", "webpack-virtual-modules": "^0.6.2" } }, "sha512-5uKD0nqiYVzlmCRs01Fhs2BdkEgBS3SAVP6ndrBsuK42iC2+JHyxM05Rm9G8+5mkmRtzMZGY8Ct5+mliZxU/Ww=="],
3205+
30903206 "unstorage": ["unstorage@1.17.5", "", { "dependencies": { "anymatch": "^3.1.3", "chokidar": "^5.0.0", "destr": "^2.0.5", "h3": "^1.15.10", "lru-cache": "^11.2.7", "node-fetch-native": "^1.6.7", "ofetch": "^1.5.1", "ufo": "^1.6.3" }, "peerDependencies": { "@azure/app-configuration": "^1.8.0", "@azure/cosmos": "^4.2.0", "@azure/data-tables": "^13.3.0", "@azure/identity": "^4.6.0", "@azure/keyvault-secrets": "^4.9.0", "@azure/storage-blob": "^12.26.0", "@capacitor/preferences": "^6 || ^7 || ^8", "@deno/kv": ">=0.9.0", "@netlify/blobs": "^6.5.0 || ^7.0.0 || ^8.1.0 || ^9.0.0 || ^10.0.0", "@planetscale/database": "^1.19.0", "@upstash/redis": "^1.34.3", "@vercel/blob": ">=0.27.1", "@vercel/functions": "^2.2.12 || ^3.0.0", "@vercel/kv": "^1 || ^2 || ^3", "aws4fetch": "^1.0.20", "db0": ">=0.2.1", "idb-keyval": "^6.2.1", "ioredis": "^5.4.2", "uploadthing": "^7.4.4" }, "optionalPeers": ["@azure/app-configuration", "@azure/cosmos", "@azure/data-tables", "@azure/identity", "@azure/keyvault-secrets", "@azure/storage-blob", "@capacitor/preferences", "@deno/kv", "@netlify/blobs", "@planetscale/database", "@upstash/redis", "@vercel/blob", "@vercel/functions", "@vercel/kv", "aws4fetch", "db0", "idb-keyval", "ioredis", "uploadthing"] }, "sha512-0i3iqvRfx29hkNntHyQvJTpf5W9dQ9ZadSoRU8+xVlhVtT7jAX57fazYO9EHvcRCfBCyi5YRya7XCDOsbTgkPg=="],
30913207
30923208 "update-browserslist-db": ["update-browserslist-db@1.2.3", "", { "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": { "update-browserslist-db": "cli.js" } }, "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w=="],
@@ -3119,7 +3235,7 @@ · 26 unmodified lines
31193235
31203236 "victory-vendor": ["victory-vendor@37.3.6", "", { "dependencies": { "@types/d3-array": "^3.0.3", "@types/d3-ease": "^3.0.0", "@types/d3-interpolate": "^3.0.1", "@types/d3-scale": "^4.0.2", "@types/d3-shape": "^3.1.0", "@types/d3-time": "^3.0.0", "@types/d3-timer": "^3.0.0", "d3-array": "^3.1.6", "d3-ease": "^3.0.1", "d3-interpolate": "^3.0.1", "d3-scale": "^4.0.2", "d3-shape": "^3.1.0", "d3-time": "^3.0.0", "d3-timer": "^3.0.1" } }, "sha512-SbPDPdDBYp+5MJHhBCAyI7wKM3d5ivekigc2Dk2s7pgbZ9wIgIBYGVw4zGHBml/qTFbexrofXW6Gu4noGxrOwQ=="],
31213237
3122− "vite": ["vite@6.4.1", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.4", "picomatch": "^4.0.2", "postcss": "^8.5.3", "rollup": "^4.34.9", "tinyglobby": "^0.2.13" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "jiti": ">=1.21.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g=="],
3238+ "vite": ["vite@8.0.5", "", { "dependencies": { "lightningcss": "^1.32.0", "picomatch": "^4.0.4", "postcss": "^8.5.8", "rolldown": "1.0.0-rc.12", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "@vitejs/devtools": "^0.1.0", "esbuild": "^0.27.0 || ^0.28.0", "jiti": ">=1.21.0", "less": "^4.0.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "@vitejs/devtools", "esbuild", "jiti", "less", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-nmu43Qvq9UopTRfMx2jOYW5l16pb3iDC1JH6yMuPkpVbzK0k+L7dfsEDH4jRgYFmsg0sTAqkojoZgzLMlwHsCQ=="],
31233239
31243240 "vite-node": ["vite-node@3.2.4", "", { "dependencies": { "cac": "^6.7.14", "debug": "^4.4.1", "es-module-lexer": "^1.7.0", "pathe": "^2.0.3", "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0" }, "bin": { "vite-node": "vite-node.mjs" } }, "sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg=="],
31253241
@@ -3147,6 +3263,12 @@ · 21 unmodified lines
31473263
31483264 "webidl-conversions": ["webidl-conversions@3.0.1", "", {}, "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="],
31493265
3266+ "webpack-virtual-modules": ["webpack-virtual-modules@0.6.2", "", {}, "sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ=="],
3267+
3268+ "whatwg-encoding": ["whatwg-encoding@3.1.1", "", { "dependencies": { "iconv-lite": "0.6.3" } }, "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ=="],
3269+
3270+ "whatwg-mimetype": ["whatwg-mimetype@4.0.0", "", {}, "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg=="],
3271+
31503272 "whatwg-url": ["whatwg-url@5.0.0", "", { "dependencies": { "tr46": "~0.0.3", "webidl-conversions": "^3.0.0" } }, "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw=="],
31513273
31523274 "which": ["which@5.0.0", "", { "dependencies": { "isexe": "^3.1.1" }, "bin": { "node-which": "bin/which.js" } }, "sha512-JEdGzHwwkrbWoGOlIHqQ5gtprKGOenpDHpxE9zVR1bWbOtYRyPPHMe9FaP6x61CmNaTThSkb0DAJte5jD+DmzQ=="],
@@ -3165,6 +3287,8 @@ · 12 unmodified lines
31653287
31663288 "xmlbuilder": ["xmlbuilder@15.1.1", "", {}, "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg=="],
31673289
3290+ "xmlbuilder2": ["xmlbuilder2@4.0.3", "", { "dependencies": { "@oozcitak/dom": "^2.0.2", "@oozcitak/infra": "^2.0.2", "@oozcitak/util": "^10.0.0", "js-yaml": "^4.1.1" } }, "sha512-bx8Q1STctnNaaDymWnkfQLKofs0mGNN7rLLapJlGuV3VlvegD7Ls4ggMjE3aUSWItCCzU0PEv45lI87iSigiCA=="],
3291+
31683292 "xtend": ["xtend@4.0.2", "", {}, "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ=="],
31693293
31703294 "xxhash-wasm": ["xxhash-wasm@1.1.0", "", {}, "sha512-147y/6YNh+tlp6nd/2pWq38i9h6mz/EuQ6njIrmW8D1BS5nCqs0P6DG+m6zTGnNz5I+uhZ0SHxBs9BsPrwcKDA=="],
@@ -3197,12 +3321,18 @@ · 26 unmodified lines
31973321
31983322 "@babel/code-frame/js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="],
31993323
3324+ "@babel/core/@babel/code-frame": ["@babel/code-frame@7.29.0", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.28.5", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" } }, "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw=="],
3325+
32003326 "@babel/core/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
32013327
32023328 "@babel/helper-compilation-targets/lru-cache": ["lru-cache@5.1.1", "", { "dependencies": { "yallist": "^3.0.2" } }, "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w=="],
32033329
32043330 "@babel/helper-compilation-targets/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
32053331
3332+ "@babel/template/@babel/code-frame": ["@babel/code-frame@7.29.0", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.28.5", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" } }, "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw=="],
3333+
3334+ "@babel/traverse/@babel/code-frame": ["@babel/code-frame@7.29.0", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.28.5", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" } }, "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw=="],
3335+
32063336 "@develar/schema-utils/ajv": ["ajv@6.14.0", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw=="],
32073337
32083338 "@electron/asar/commander": ["commander@5.1.0", "", {}, "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg=="],
@@ -3235,10 +3365,6 @@ · 26 unmodified lines
32353365
32363366 "@esbuild-kit/core-utils/esbuild": ["esbuild@0.18.20", "", { "optionalDependencies": { "@esbuild/android-arm": "0.18.20", "@esbuild/android-arm64": "0.18.20", "@esbuild/android-x64": "0.18.20", "@esbuild/darwin-arm64": "0.18.20", "@esbuild/darwin-x64": "0.18.20", "@esbuild/freebsd-arm64": "0.18.20", "@esbuild/freebsd-x64": "0.18.20", "@esbuild/linux-arm": "0.18.20", "@esbuild/linux-arm64": "0.18.20", "@esbuild/linux-ia32": "0.18.20", "@esbuild/linux-loong64": "0.18.20", "@esbuild/linux-mips64el": "0.18.20", "@esbuild/linux-ppc64": "0.18.20", "@esbuild/linux-riscv64": "0.18.20", "@esbuild/linux-s390x": "0.18.20", "@esbuild/linux-x64": "0.18.20", "@esbuild/netbsd-x64": "0.18.20", "@esbuild/openbsd-x64": "0.18.20", "@esbuild/sunos-x64": "0.18.20", "@esbuild/win32-arm64": "0.18.20", "@esbuild/win32-ia32": "0.18.20", "@esbuild/win32-x64": "0.18.20" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA=="],
32373367
3238− "@executor/config/typescript": ["typescript@6.0.2", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-bGdAIrZ0wiGDo5l8c++HWtbaNCWTS4UTv7RaTH/ThVIgjkveJt83m74bBHMJkuCbslY8ixgLBVZJIOiQlQTjfQ=="],
3239−
3240− "@executor/sdk/typescript": ["typescript@6.0.2", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-bGdAIrZ0wiGDo5l8c++HWtbaNCWTS4UTv7RaTH/ThVIgjkveJt83m74bBHMJkuCbslY8ixgLBVZJIOiQlQTjfQ=="],
3241−
32423368 "@isaacs/cliui/string-width": ["string-width@5.1.2", "", { "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", "strip-ansi": "^7.0.1" } }, "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA=="],
32433369
32443370 "@isaacs/cliui/strip-ansi": ["strip-ansi@7.2.0", "", { "dependencies": { "ansi-regex": "^6.2.2" } }, "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w=="],
@@ -3275,6 +3401,18 @@ · 30 unmodified lines
32753401
32763402 "@tailwindcss/oxide-wasm32-wasi/tslib": ["tslib@2.8.1", "", { "bundled": true }, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
32773403
3404+ "@tanstack/router-generator/prettier": ["prettier@3.8.1", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg=="],
3405+
3406+ "@tanstack/router-generator/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="],
3407+
3408+ "@tanstack/router-plugin/chokidar": ["chokidar@3.6.0", "", { "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", "readdirp": "~3.6.0" }, "optionalDependencies": { "fsevents": "~2.3.2" } }, "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw=="],
3409+
3410+ "@tanstack/router-plugin/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="],
3411+
3412+ "@tanstack/start-plugin-core/@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.0-beta.40", "", {}, "sha512-s3GeJKSQOwBlzdUrj4ISjJj5SfSh+aqn0wjOar4Bx95iV1ETI7F6S/5hLcfAxZ9kXDcyrAkxPlqmd1ZITttf+w=="],
3413+
3414+ "@tanstack/start-plugin-core/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="],
3415+
32783416 "@types/accepts/@types/node": ["@types/node@25.5.0", "", { "dependencies": { "undici-types": "~7.18.0" } }, "sha512-jp2P3tQMSxWugkCUKLRPVUpGaL5MVFwF8RDuSRztfwgN1wmqJeMSbKlnEtQqU8UrhTmzEmZdu2I6v2dpp7XIxw=="],
32793417
32803418 "@types/body-parser/@types/node": ["@types/node@25.5.0", "", { "dependencies": { "undici-types": "~7.18.0" } }, "sha512-jp2P3tQMSxWugkCUKLRPVUpGaL5MVFwF8RDuSRztfwgN1wmqJeMSbKlnEtQqU8UrhTmzEmZdu2I6v2dpp7XIxw=="],
@@ -3309,6 +3447,8 @@ · 28 unmodified lines
33093447
33103448 "@vercel/routing-utils/ajv": ["ajv@6.14.0", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw=="],
33113449
3450+ "@vitest/mocker/vite": ["vite@6.4.1", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.4", "picomatch": "^4.0.2", "postcss": "^8.5.3", "rollup": "^4.34.9", "tinyglobby": "^0.2.13" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "jiti": ">=1.21.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g=="],
3451+
33123452 "ajv-keywords/ajv": ["ajv@6.14.0", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw=="],
33133453
33143454 "anymatch/picomatch": ["picomatch@2.3.2", "", {}, "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA=="],
@@ -3371,8 +3511,6 @@ · 56 unmodified lines
33713511
33723512 "dmg-license/ajv": ["ajv@6.14.0", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw=="],
33733513
3374− "dom-serializer/entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="],
3375−
33763514 "electron/@types/node": ["@types/node@22.19.17", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-wGdMcf+vPYM6jikpS/qhg6WiqSV/OhG+jeeHT/KlVqxYfD40iYJf9/AE1uQxVWFvU7MipKRkRv8NSHiCGgPr8Q=="],
33773515
33783516 "electron-builder/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="],
@@ -3387,6 +3525,8 @@ · 8 unmodified lines
33873525
33883526 "encoding/iconv-lite": ["iconv-lite@0.6.3", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw=="],
33893527
3528+ "encoding-sniffer/iconv-lite": ["iconv-lite@0.6.3", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw=="],
3529+
33903530 "express/cookie": ["cookie@0.7.2", "", {}, "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w=="],
33913531
33923532 "express/qs": ["qs@6.15.0", "", { "dependencies": { "side-channel": "^1.1.0" } }, "sha512-mAZTtNCeetKMH+pSjrb76NAM8V9a05I9aBZOHztWy/UqcJdQYNsf59vrRKWnojAT9Y+GbIvoTBC++CPHqpDBhQ=="],
@@ -3401,6 +3541,8 @@ · 8 unmodified lines
34013541
34023542 "hosted-git-info/lru-cache": ["lru-cache@6.0.0", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA=="],
34033543
3544+ "htmlparser2/entities": ["entities@7.0.1", "", {}, "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA=="],
3545+
34043546 "iconv-corefoundation/node-addon-api": ["node-addon-api@1.7.2", "", {}, "sha512-ibPK3iA+vaY1eEjESkQkM0BbCqFOaZMiXRTtdB0u7b4djtY6JnsjvPdUHVMg6xQt3B8fpTTWHI9A+ADjM9frzg=="],
34053547
34063548 "iron-session/@types/node": ["@types/node@17.0.45", "", {}, "sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw=="],
@@ -3429,6 +3571,8 @@ · 22 unmodified lines
34293571
34303572 "parse-entities/@types/unist": ["@types/unist@2.0.11", "", {}, "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA=="],
34313573
3574+ "parse5/entities": ["entities@6.0.1", "", {}, "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g=="],
3575+
34323576 "postject/commander": ["commander@9.5.0", "", {}, "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ=="],
34333577
34343578 "proper-lockfile/signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="],
@@ -3437,12 +3581,18 @@ · 2 unmodified lines
34373581
34383582 "read-yaml-file/js-yaml": ["js-yaml@3.14.2", "", { "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg=="],
34393583
3584+ "recast/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="],
3585+
34403586 "restore-cursor/signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="],
34413587
34423588 "rimraf/glob": ["glob@7.2.3", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="],
34433589
3590+ "rolldown/@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.0-rc.12", "", {}, "sha512-HHMwmarRKvoFsJorqYlFeFRzXZqCt2ETQlEDOb9aqssrnVBB1/+xgTGtuTrIk5vzLNX1MjMtTf7W9z3tsSbrxw=="],
3591+
34443592 "router/path-to-regexp": ["path-to-regexp@8.4.2", "", {}, "sha512-qRcuIdP69NPm4qbACK+aDogI5CBDMi1jKe0ry5rSQJz8JVLsC7jV8XpiJjGRLLol3N+R5ihGYcrPLTno6pAdBA=="],
34453593
3594+ "source-map-support/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="],
3595+
34463596 "tar-fs/chownr": ["chownr@1.1.4", "", {}, "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg=="],
34473597
34483598 "temp-file/fs-extra": ["fs-extra@10.1.0", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ=="],
@@ -3457,6 +3607,8 @@ · 8 unmodified lines
34573607
34583608 "vitest/vite": ["vite@7.3.1", "", { "dependencies": { "esbuild": "^0.27.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rollup": "^4.43.0", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", "less": "^4.0.0", "lightningcss": "^1.21.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA=="],
34593609
3610+ "whatwg-encoding/iconv-lite": ["iconv-lite@0.6.3", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw=="],
3611+
34603612 "yargs/yargs-parser": ["yargs-parser@21.1.1", "", {}, "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw=="],
34613613
34623614 "@astrojs/vercel/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.27.4", "", { "os": "aix", "cpu": "ppc64" }, "sha512-cQPwL2mp2nSmHHJlCyoXgHGhbEPMrEEU5xhkcy3Hs/O7nGZqEpZ2sUtLaL9MORLtDfRvVl2/3PAuEkYZH0Ty8Q=="],
@@ -3511,8 +3663,14 @@ · 48 unmodified lines
35113663
35123664 "@astrojs/vercel/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.27.4", "", { "os": "win32", "cpu": "x64" }, "sha512-+knoa0BDoeXgkNvvV1vvbZX4+hizelrkwmGJBdT17t8FNPwG2lKemmuMZlmaNQ3ws3DKKCxpb4zRZEIp3UxFCg=="],
35133665
3666+ "@babel/core/@babel/code-frame/js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="],
3667+
35143668 "@babel/helper-compilation-targets/lru-cache/yallist": ["yallist@3.1.1", "", {}, "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="],
35153669
3670+ "@babel/template/@babel/code-frame/js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="],
3671+
3672+ "@babel/traverse/@babel/code-frame/js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="],
3673+
35163674 "@develar/schema-utils/ajv/json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="],
35173675
35183676 "@electron/asar/minimatch/brace-expansion": ["brace-expansion@1.1.13", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w=="],
@@ -3593,6 +3751,8 @@ · 74 unmodified lines
35933751
35943752 "@malept/flatpak-bundler/fs-extra/universalify": ["universalify@2.0.1", "", {}, "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw=="],
35953753
3754+ "@tanstack/router-plugin/chokidar/readdirp": ["readdirp@3.6.0", "", { "dependencies": { "picomatch": "^2.2.1" } }, "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA=="],
3755+
35963756 "@types/accepts/@types/node/undici-types": ["undici-types@7.18.2", "", {}, "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w=="],
35973757
35983758 "@types/body-parser/@types/node/undici-types": ["undici-types@7.18.2", "", {}, "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w=="],
@@ -3807,6 +3967,8 @@ · 208 unmodified lines
38073967
38083968 "@electron/universal/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="],
38093969
3970+ "@tanstack/router-plugin/chokidar/readdirp/picomatch": ["picomatch@2.3.2", "", {}, "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA=="],
3971+
38103972 "cacache/glob/minimatch/brace-expansion": ["brace-expansion@2.0.3", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA=="],
38113973
38123974 "dir-compare/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="],
package.json+12−1
@@ -42,7 +42,18 @@ · 41 unmodified lines
4242 "@types/node": "^24.3.1",
4343 "bun-types": "^1.2.22",
4444 "drizzle-orm": "^0.44.0",
45− "vitest": "^3.2.4"
45+ "vitest": "^3.2.4",
46+ "vite": "^8.0.0",
47+ "@vitejs/plugin-react": "^6.0.1",
48+ "@tailwindcss/vite": "^4.2.2",
49+ "@tanstack/react-router": "^1.168.10",
50+ "@tanstack/react-start": "^1.167.16",
51+ "react": "^19.1.0",
52+ "react-dom": "^19.1.0",
53+ "@types/react": "^19.1.0",
54+ "@types/react-dom": "^19.1.0",
55+ "typescript": "^5.9.3",
56+ "tailwindcss": "^4.2.2"
4657 },
4758 "scripts": {
4859 "dev": "turbo run dev --filter='!@executor/desktop'",
packages/core/api/package.json+1−1
@@ -15,7 +15,7 @@ · 14 unmodified lines
1515 "devDependencies": {
1616 "@types/node": "catalog:",
1717 "bun-types": "catalog:",
18− "typescript": "^5.9.3"
18+ "typescript": "catalog:"
1919 },
2020 "scripts": {
2121 "typecheck": "tsc --noEmit"
packages/core/config/package.json+1−1
@@ -20,6 +20,6 @@ · 19 unmodified lines
2020 "@effect/platform-node": "catalog:",
2121 "@effect/vitest": "catalog:",
2222 "vitest": "catalog:",
23− "typescript": "latest"
23+ "typescript": "catalog:"
2424 }
2525 }
packages/core/sdk/package.json+1−1
@@ -16,6 +16,6 @@ · 15 unmodified lines
1616 "devDependencies": {
1717 "@effect/vitest": "catalog:",
1818 "vitest": "catalog:",
19− "typescript": "latest"
19+ "typescript": "catalog:"
2020 }
2121 }
packages/core/storage-file/package.json+1−1
@@ -15,7 +15,7 @@ · 14 unmodified lines
1515 "@effect/experimental": "catalog:",
1616 "@effect/sql-sqlite-node": "catalog:",
1717 "@effect/vitest": "catalog:",
18− "typescript": "^5.9.3",
18+ "typescript": "catalog:",
1919 "vitest": "catalog:"
2020 },
2121 "scripts": {
packages/core/storage-postgres/package.json+1−1
@@ -19,7 +19,7 @@ · 18 unmodified lines
1919 "@electric-sql/pglite": "^0.4.3",
2020 "@types/pg": "^8.15.4",
2121 "drizzle-kit": "^0.31.0",
22− "typescript": "^5.9.3",
22+ "typescript": "catalog:",
2323 "vitest": "catalog:"
2424 },
2525 "scripts": {
packages/plugins/google-discovery/package.json+4−4
@@ -21,9 +21,9 @@ · 20 unmodified lines
2121 "effect": "catalog:"
2222 },
2323 "peerDependencies": {
24− "react": "^19.1.0",
24+ "react": "catalog:",
2525 "@effect-atom/atom-react": "^0.5.0",
26− "@tanstack/react-router": "^1.168.10",
26+ "@tanstack/react-router": "catalog:",
2727 "@executor/react": "workspace:*"
2828 },
2929 "peerDependenciesMeta": {
@@ -45,9 +45,9 @@ · 15 unmodified lines
4545 "@effect/vitest": "catalog:",
4646 "@executor/react": "workspace:*",
4747 "@types/node": "catalog:",
48− "@types/react": "^19.1.0",
48+ "@types/react": "catalog:",
4949 "bun-types": "catalog:",
50− "react": "^19.1.0",
50+ "react": "catalog:",
5151 "vitest": "catalog:"
5252 }
5353 }
packages/plugins/graphql/package.json+4−4
@@ -21,9 +21,9 @@ · 20 unmodified lines
2121 "effect": "catalog:"
2222 },
2323 "peerDependencies": {
24− "react": "^19.1.0",
24+ "react": "catalog:",
2525 "@effect-atom/atom-react": "^0.5.0",
26− "@tanstack/react-router": "^1.168.10",
26+ "@tanstack/react-router": "catalog:",
2727 "@executor/api": "workspace:*",
2828 "@executor/react": "workspace:*"
2929 },
@@ -45,11 +45,11 @@ · 15 unmodified lines
4545 }
4646 },
4747 "devDependencies": {
48− "react": "^19.1.0",
48+ "react": "catalog:",
4949 "@effect-atom/atom-react": "^0.5.0",
5050 "@executor/api": "workspace:*",
5151 "@executor/react": "workspace:*",
52− "@types/react": "^19.1.0",
52+ "@types/react": "catalog:",
5353 "@effect/vitest": "catalog:",
5454 "@types/node": "catalog:",
5555 "bun-types": "catalog:",
packages/plugins/mcp/package.json+4−4
@@ -22,9 +22,9 @@ · 21 unmodified lines
2222 "effect": "catalog:"
2323 },
2424 "peerDependencies": {
25− "react": "^19.1.0",
25+ "react": "catalog:",
2626 "@effect-atom/atom-react": "^0.5.0",
27− "@tanstack/react-router": "^1.168.10",
27+ "@tanstack/react-router": "catalog:",
2828 "@executor/api": "workspace:*",
2929 "@executor/react": "workspace:*"
3030 },
@@ -46,11 +46,11 @@ · 15 unmodified lines
4646 }
4747 },
4848 "devDependencies": {
49− "react": "^19.1.0",
49+ "react": "catalog:",
5050 "@effect-atom/atom-react": "^0.5.0",
5151 "@executor/api": "workspace:*",
5252 "@executor/react": "workspace:*",
53− "@types/react": "^19.1.0",
53+ "@types/react": "catalog:",
5454 "@effect/vitest": "catalog:",
5555 "@types/node": "catalog:",
5656 "bun-types": "catalog:",
packages/plugins/onepassword/package.json+2−2
@@ -25,9 +25,9 @@ · 24 unmodified lines
2525 "devDependencies": {
2626 "@effect/vitest": "catalog:",
2727 "@types/node": "catalog:",
28− "@types/react": "^19.1.0",
28+ "@types/react": "catalog:",
2929 "bun-types": "catalog:",
30− "react": "^19.1.0",
30+ "react": "catalog:",
3131 "vitest": "catalog:"
3232 },
3333 "peerDependencies": {
packages/plugins/openapi/package.json+4−4
@@ -24,9 +24,9 @@ · 23 unmodified lines
2424 "yaml": "^2.7.1"
2525 },
2626 "peerDependencies": {
27− "react": "^19.1.0",
27+ "react": "catalog:",
2828 "@effect-atom/atom-react": "^0.5.0",
29− "@tanstack/react-router": "^1.168.10",
29+ "@tanstack/react-router": "catalog:",
3030 "@executor/api": "workspace:*",
3131 "@executor/react": "workspace:*"
3232 },
@@ -48,11 +48,11 @@ · 15 unmodified lines
4848 }
4949 },
5050 "devDependencies": {
51− "react": "^19.1.0",
51+ "react": "catalog:",
5252 "@effect-atom/atom-react": "^0.5.0",
5353 "@executor/api": "workspace:*",
5454 "@executor/react": "workspace:*",
55− "@types/react": "^19.1.0",
55+ "@types/react": "catalog:",
5656 "@effect/vitest": "catalog:",
5757 "@types/node": "catalog:",
5858 "bun-types": "catalog:",
packages/react/package.json+4−4
@@ -32,7 +32,7 @@ · 31 unmodified lines
3232 "lucide-react": "^1.7.0",
3333 "next-themes": "^0.4.6",
3434 "radix-ui": "^1.4.3",
35− "react": "^19.1.0",
35+ "react": "catalog:",
3636 "react-day-picker": "^9.14.0",
3737 "react-hook-form": "^7.72.0",
3838 "react-resizable-panels": "^4",
@@ -45,11 +45,11 @@ · 6 unmodified lines
4545 "zod": "^4.3.6"
4646 },
4747 "devDependencies": {
48− "@types/react": "^19.1.0",
48+ "@types/react": "catalog:",
4949 "@types/node": "catalog:",
5050 "hast-util-to-jsx-runtime": "^2.3.6",
51− "tailwindcss": "^4.1.10",
52− "typescript": "^5.9.3"
51+ "tailwindcss": "catalog:",
52+ "typescript": "catalog:"
5353 },
5454 "scripts": {
5555 "typecheck": "tsc --noEmit"
packages/react/src/components/mcp-install-card.tsx+3−3
@@ -1,7 +1,7 @@
11 import { useEffect, useState } from "react";
2−import { Button } from "@executor/ui/components/button";
3−import { CodeBlock } from "@executor/ui/components/code-block";
4−import { useScopeInfo } from "@executor/react";
2+import { Button } from "./button";
3+import { CodeBlock } from "./code-block";
4+import { useScopeInfo } from "../api/scope-context";
55
66 type TransportMode = "stdio" | "http";
77
packages/react/src/styles/globals.css+4−5
@@ -2,11 +2,10 @@ · 1 unmodified line
22
33 @custom-variant dark (&:is(.dark *));
44
5−@source "../components/**/*.{ts,tsx}";
6−@source "../../../../apps/web/src/**/*.{ts,tsx}";
7−@source "../../../clients/react/src/**/*.{ts,tsx}";
8−@source "../../../plugins/openapi/src/react/**/*.{ts,tsx}";
9−@source "../../../plugins/onepassword/src/react/**/*.{ts,tsx}";
5+@source "../**/*.{ts,tsx}";
6+@source "../../../../apps/local/src/**/*.{ts,tsx}";
7+@source "../../../../apps/cloud/src/**/*.{ts,tsx}";
8+@source "../../../plugins/*/src/react/**/*.{ts,tsx}";
109
1110 @theme inline {
1211 --font-sans: "DM Sans", ui-sans-serif, system-ui, sans-serif;