diff --git a/examples/queue-sandbox-vercel/README.md b/examples/queue-sandbox-vercel/README.md index 378f0f6772..5bbc5880ae 100644 --- a/examples/queue-sandbox-vercel/README.md +++ b/examples/queue-sandbox-vercel/README.md @@ -9,12 +9,14 @@ Interactive demo showcasing all the ways to use queues in RivetKit. Each tab dem ## Getting Started -```bash -cd examples/queue-sandbox -pnpm install -pnpm dev +```sh +git clone https://github.com/rivet-dev/rivet.git +cd rivet/examples/queue-sandbox +npm install +npm run dev ``` + ## Features - Six interactive tabs demonstrating different queue patterns diff --git a/examples/queue-sandbox-vercel/tsconfig.json b/examples/queue-sandbox-vercel/tsconfig.json index 2a870bab03..91635880bc 100644 --- a/examples/queue-sandbox-vercel/tsconfig.json +++ b/examples/queue-sandbox-vercel/tsconfig.json @@ -3,7 +3,8 @@ "target": "esnext", "lib": [ "esnext", - "dom" + "dom", + "dom.iterable" ], "jsx": "react-jsx", "module": "esnext", diff --git a/examples/queue-sandbox/README.md b/examples/queue-sandbox/README.md index 67f7d8df1f..18d032f10e 100644 --- a/examples/queue-sandbox/README.md +++ b/examples/queue-sandbox/README.md @@ -4,12 +4,14 @@ Interactive demo showcasing all the ways to use queues in RivetKit. Each tab dem ## Getting Started -```bash -cd examples/queue-sandbox -pnpm install -pnpm dev +```sh +git clone https://github.com/rivet-dev/rivet.git +cd rivet/examples/queue-sandbox +npm install +npm run dev ``` + ## Features - Six interactive tabs demonstrating different queue patterns diff --git a/frontend/packages/example-registry/src/_gen.ts b/frontend/packages/example-registry/src/_gen.ts index 35184fc2e7..3c1ef77046 100644 --- a/frontend/packages/example-registry/src/_gen.ts +++ b/frontend/packages/example-registry/src/_gen.ts @@ -60,6 +60,27 @@ export const templates: Template[] = [ } } }, + { + "name": "queue-sandbox", + "displayName": "Queue Sandbox", + "description": "Interactive demo showcasing all the ways to use queues in RivetKit. Each tab demonstrates a different queue pattern with real-time feedback.", + "technologies": [ + "rivet", + "typescript", + "react" + ], + "tags": [ + "queues" + ], + "noFrontend": false, + "priority": 100, + "providers": { + "vercel": { + "name": "queue-sandbox-vercel", + "deployUrl": "https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Frivet-gg%2Frivet%2Ftree%2Fmain%2Fexamples%2Fqueue-sandbox-vercel&project-name=queue-sandbox-vercel" + } + } + }, { "name": "chat-room", "displayName": "Chat Room", @@ -327,7 +348,12 @@ export const templates: Template[] = [ "database" ], "noFrontend": true, - "providers": {} + "providers": { + "vercel": { + "name": "drizzle-vercel", + "deployUrl": "https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Frivet-gg%2Frivet%2Ftree%2Fmain%2Fexamples%2Fdrizzle-vercel&project-name=drizzle-vercel" + } + } }, { "name": "elysia", @@ -533,5 +559,25 @@ export const templates: Template[] = [ "deployUrl": "https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Frivet-gg%2Frivet%2Ftree%2Fmain%2Fexamples%2Ftrpc-vercel&project-name=trpc-vercel" } } + }, + { + "name": "workflow-sandbox", + "displayName": "Workflow Sandbox", + "description": "Interactive sandbox for testing all RivetKit workflow patterns.", + "technologies": [ + "rivet", + "react", + "typescript" + ], + "tags": [ + "experimental" + ], + "noFrontend": false, + "providers": { + "vercel": { + "name": "workflow-sandbox-vercel", + "deployUrl": "https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Frivet-gg%2Frivet%2Ftree%2Fmain%2Fexamples%2Fworkflow-sandbox-vercel&project-name=workflow-sandbox-vercel" + } + } } ]; diff --git a/frontend/packages/example-registry/src/const.ts b/frontend/packages/example-registry/src/const.ts index e17191042e..33115840af 100644 --- a/frontend/packages/example-registry/src/const.ts +++ b/frontend/packages/example-registry/src/const.ts @@ -27,6 +27,7 @@ export const TAGS = [ { name: "database", displayName: "Database" }, { name: "gaming", displayName: "Gaming" }, { name: "experimental", displayName: "Experimental" }, + { name: 'queues', displayName: 'Queues' }, ] as const; export type Technology = (typeof TECHNOLOGIES)[number]["name"]; diff --git a/frontend/src/app/actor-builds-list.tsx b/frontend/src/app/actor-builds-list.tsx index ece00a039b..1b90d6abd9 100644 --- a/frontend/src/app/actor-builds-list.tsx +++ b/frontend/src/app/actor-builds-list.tsx @@ -33,6 +33,24 @@ function lookupFaIcon(iconName: string): IconProp | null { return iconDef ?? null; } +function getActorIcon(iconValue: string | null) { + if (iconValue && isEmoji(iconValue)) { + return ( + + {iconValue} + + ); + } + + const faIcon = iconValue ? lookupFaIcon(iconValue) : null; + return ( + + ); +} + export function ActorBuildsList() { const { data, isLoading, hasNextPage, fetchNextPage, isFetchingNextPage } = useInfiniteQuery(useDataProvider().buildsQueryOptions()); @@ -57,23 +75,7 @@ export function ActorBuildsList() { ? build.name.metadata.name : build.id; - const iconElement = useMemo(() => { - if (iconValue && isEmoji(iconValue)) { - return ( - - {iconValue} - - ); - } - - const faIcon = iconValue ? lookupFaIcon(iconValue) : null; - return ( - - ); - }, [iconValue]); + const iconElement = getActorIcon(iconValue); return ( + + + + ); +} diff --git a/frontend/src/app/dialogs/confirm-delete-project-frame.tsx b/frontend/src/app/dialogs/confirm-delete-project-frame.tsx new file mode 100644 index 0000000000..4547008ecf --- /dev/null +++ b/frontend/src/app/dialogs/confirm-delete-project-frame.tsx @@ -0,0 +1,83 @@ +import { useMutation } from "@tanstack/react-query"; +import { useNavigate } from "@tanstack/react-router"; +import posthog from "posthog-js"; +import { useState } from "react"; +import { Button, type DialogContentProps, Frame } from "@/components"; +import { useCloudProjectDataProvider } from "@/components/actors"; +import { Input } from "@/components/ui/input"; +import { Label } from "@/components/ui/label"; +import { queryClient } from "@/queries/global"; + +interface ConfirmDeleteProjectContentProps extends DialogContentProps { + displayName: string; +} + +export default function ConfirmDeleteProjectContent({ + onClose, + displayName, +}: ConfirmDeleteProjectContentProps) { + const dataProvider = useCloudProjectDataProvider(); + const navigate = useNavigate(); + const [confirmValue, setConfirmValue] = useState(""); + + const isConfirmed = confirmValue === displayName; + + const { mutate, isPending } = useMutation({ + ...dataProvider.archiveCurrentProjectMutationOptions(), + onSuccess: async () => { + posthog.capture("project_deleted", { + displayName, + }); + await queryClient.invalidateQueries(); + onClose?.(); + return navigate({ + to: "/orgs/$organization", + from: "/orgs/$organization/projects/$project", + }); + }, + }); + + return ( + <> + + +
Confirm archival of '{displayName}' project
+
+ + Archiving this project will permanently remove all associated + namespaces, Rivet Actors, Runners, and configurations. This + action cannot be undone. + +
+ +
+ + setConfirmValue(e.target.value)} + placeholder={displayName} + /> +
+
+ + + + + + ); +} diff --git a/frontend/src/app/layout.tsx b/frontend/src/app/layout.tsx index 99da561951..4a6436c611 100644 --- a/frontend/src/app/layout.tsx +++ b/frontend/src/app/layout.tsx @@ -209,6 +209,17 @@ const Sidebar = ({ > Settings + ) : matchRoute({ + to: "/orgs/$organization/projects/$project", + fuzzy: true, + }) ? ( + + Settings + ) : null} {matchRoute({ to: "/orgs/$organization/projects/$project/ns/$namespace", diff --git a/frontend/src/app/metrics/types.ts b/frontend/src/app/metrics/types.ts index e118a6d181..d854b8aebf 100644 --- a/frontend/src/app/metrics/types.ts +++ b/frontend/src/app/metrics/types.ts @@ -1,6 +1,6 @@ import type { Rivet } from "@rivet-gg/cloud"; -export type MetricName = Rivet.namespaces.MetricsGetRequestNameItem; +export type MetricName = Rivet.MetricName; export interface MetricConfig { name: MetricName; diff --git a/frontend/src/app/use-dialog.tsx b/frontend/src/app/use-dialog.tsx index 553477b6b1..2c0e159d8c 100644 --- a/frontend/src/app/use-dialog.tsx +++ b/frontend/src/app/use-dialog.tsx @@ -41,6 +41,12 @@ export const useDialog = { DeleteConfig: createDialogHook( () => import("@/app/dialogs/confirm-delete-config-frame"), ), + DeleteNamespace: createDialogHook( + () => import("@/app/dialogs/confirm-delete-namespace-frame"), + ), + DeleteProject: createDialogHook( + () => import("@/app/dialogs/confirm-delete-project-frame"), + ), Billing: createDialogHook(() => import("@/app/dialogs/billing-frame")), ProvideEngineCredentials: createDialogHook( () => import("@/app/dialogs/provide-engine-credentials-frame"), diff --git a/frontend/src/components/actors/actor-inspector-context.tsx b/frontend/src/components/actors/actor-inspector-context.tsx index 6a6e9e3363..55dbe59ae8 100644 --- a/frontend/src/components/actors/actor-inspector-context.tsx +++ b/frontend/src/components/actors/actor-inspector-context.tsx @@ -16,7 +16,7 @@ import { type QueueStatus, } from "rivetkit/inspector"; import type { ReadRangeOptions, ReadRangeWire } from "@rivetkit/traces"; -import { decodeReadRangeWire } from "@rivetkit/traces/reader"; +import { decodeReadRangeWire } from "@rivetkit/traces/encoding"; import { toast } from "sonner"; import { match } from "ts-pattern"; import z from "zod"; diff --git a/frontend/src/components/actors/actor-traces.tsx b/frontend/src/components/actors/actor-traces.tsx index 4ad108b85e..7931d4e71e 100644 --- a/frontend/src/components/actors/actor-traces.tsx +++ b/frontend/src/components/actors/actor-traces.tsx @@ -1,13 +1,18 @@ import { faChevronDown, faSpinnerThird, Icon } from "@rivet-gg/icons"; +import type { + OtlpAnyValue, + OtlpExportTraceServiceRequestJson, + OtlpKeyValue, + OtlpSpan, + OtlpSpanEvent, +} from "@rivetkit/traces"; +import { readRangeWireToOtlp } from "@rivetkit/traces/otlp"; import { useQuery } from "@tanstack/react-query"; import { format } from "date-fns"; -import { - useMemo, - useState, - type ReactElement, -} from "react"; +import { type ReactElement, useMemo, useState } from "react"; import type { DateRange } from "../datepicker"; import { RangeDatePicker } from "../datepicker"; +import { cn } from "../lib/utils"; import { Button } from "../ui/button"; import { Select, @@ -16,18 +21,9 @@ import { SelectTrigger, SelectValue, } from "../ui/select"; -import { cn } from "../lib/utils"; -import { ActorObjectInspector } from "./console/actor-inspector"; import { useActorInspector } from "./actor-inspector-context"; +import { ActorObjectInspector } from "./console/actor-inspector"; import type { ActorId } from "./queries"; -import { readRangeWireToOtlp } from "@rivetkit/traces/reader"; -import type { - OtlpAnyValue, - OtlpExportTraceServiceRequestJson, - OtlpKeyValue, - OtlpSpan, - OtlpSpanEvent, -} from "@rivetkit/traces"; const PRESET_OPTIONS = [ { label: "5 min", ms: 5 * 60 * 1000 }, @@ -63,13 +59,15 @@ export function ActorTraces({ actorId }: { actorId: ActorId }) { const inspector = useActorInspector(); const [isLive, setIsLive] = useState(true); const [presetMs, setPresetMs] = useState(DEFAULT_PRESET_MS); - const [customRange, setCustomRange] = useState(() => { - const now = Date.now(); - return { - from: new Date(now - DEFAULT_PRESET_MS), - to: new Date(now), - }; - }); + const [customRange, setCustomRange] = useState( + () => { + const now = Date.now(); + return { + from: new Date(now - DEFAULT_PRESET_MS), + to: new Date(now), + }; + }, + ); const query = useQuery({ queryKey: [ @@ -86,10 +84,10 @@ export function ActorTraces({ actorId }: { actorId: ActorId }) { const now = Date.now(); const rangeStartMs = isLive ? now - presetMs - : customRange?.from?.getTime() ?? now - presetMs; + : (customRange?.from?.getTime() ?? now - presetMs); const rangeEndMs = isLive ? now - : customRange?.to?.getTime() ?? now; + : (customRange?.to?.getTime() ?? now); const startMs = Math.min(rangeStartMs, rangeEndMs); const endMs = Math.max(rangeStartMs, rangeEndMs); return inspector.api.getTraces({ @@ -98,7 +96,9 @@ export function ActorTraces({ actorId }: { actorId: ActorId }) { limit: DEFAULT_LIMIT, }); }, - enabled: inspector.isInspectorAvailable && inspector.features.traces.supported, + enabled: + inspector.isInspectorAvailable && + inspector.features.traces.supported, refetchInterval: isLive ? 1000 : false, staleTime: 0, }); @@ -433,9 +433,7 @@ function GapMarker({ ms, depth }: { ms: number; depth: number }) { ); } -function extractSpans( - otlp: OtlpExportTraceServiceRequestJson, -): OtlpSpan[] { +function extractSpans(otlp: OtlpExportTraceServiceRequestJson): OtlpSpan[] { const spans: OtlpSpan[] = []; for (const resource of otlp.resourceSpans ?? []) { for (const scope of resource.scopeSpans ?? []) { @@ -548,9 +546,7 @@ function otlpAnyValueToJs(value?: OtlpAnyValue): unknown { return value.bytesValue; } if (value.arrayValue?.values) { - return value.arrayValue.values.map((item) => - otlpAnyValueToJs(item), - ); + return value.arrayValue.values.map((item) => otlpAnyValueToJs(item)); } if (value.kvlistValue?.values) { const obj: Record = {}; diff --git a/frontend/src/content/billing.ts b/frontend/src/content/billing.ts index 40bdbf7e37..9e92d84263 100644 --- a/frontend/src/content/billing.ts +++ b/frontend/src/content/billing.ts @@ -44,7 +44,7 @@ const ACTOR_AWAKE_PRICE_PER_SECOND = */ type BilledMetrics = Extract< - Rivet.namespaces.MetricsGetRequestNameItem, + Rivet.MetricName, | "actor_awake" | "kv_storage_used" | "kv_read" diff --git a/frontend/src/routeTree.gen.ts b/frontend/src/routeTree.gen.ts index 7c3e22c3c5..01dd4734bd 100644 --- a/frontend/src/routeTree.gen.ts +++ b/frontend/src/routeTree.gen.ts @@ -31,6 +31,7 @@ import { Route as ContextCloudOrgsOrganizationNewIndexRouteImport } from './rout import { Route as ContextCloudOrgsOrganizationProjectsProjectRouteImport } from './routes/_context/_cloud/orgs.$organization/projects.$project' import { Route as ContextCloudOrgsOrganizationNewTemplateRouteImport } from './routes/_context/_cloud/orgs.$organization/new/$template' import { Route as ContextCloudOrgsOrganizationProjectsProjectIndexRouteImport } from './routes/_context/_cloud/orgs.$organization/projects.$project/index' +import { Route as ContextCloudOrgsOrganizationProjectsProjectSettingsRouteImport } from './routes/_context/_cloud/orgs.$organization/projects.$project/settings' import { Route as ContextCloudOrgsOrganizationProjectsProjectMetricsRouteImport } from './routes/_context/_cloud/orgs.$organization/projects.$project/metrics' import { Route as ContextCloudOrgsOrganizationProjectsProjectBillingRouteImport } from './routes/_context/_cloud/orgs.$organization/projects.$project/billing' import { Route as ContextCloudOrgsOrganizationProjectsProjectNsNamespaceRouteImport } from './routes/_context/_cloud/orgs.$organization/projects.$project/ns.$namespace' @@ -160,6 +161,12 @@ const ContextCloudOrgsOrganizationProjectsProjectIndexRoute = path: '/', getParentRoute: () => ContextCloudOrgsOrganizationProjectsProjectRoute, } as any) +const ContextCloudOrgsOrganizationProjectsProjectSettingsRoute = + ContextCloudOrgsOrganizationProjectsProjectSettingsRouteImport.update({ + id: '/settings', + path: '/settings', + getParentRoute: () => ContextCloudOrgsOrganizationProjectsProjectRoute, + } as any) const ContextCloudOrgsOrganizationProjectsProjectMetricsRoute = ContextCloudOrgsOrganizationProjectsProjectMetricsRouteImport.update({ id: '/metrics', @@ -254,6 +261,7 @@ export interface FileRoutesByFullPath { '/orgs/$organization/projects': typeof ContextCloudOrgsOrganizationProjectsIndexRoute '/orgs/$organization/projects/$project/billing': typeof ContextCloudOrgsOrganizationProjectsProjectBillingRoute '/orgs/$organization/projects/$project/metrics': typeof ContextCloudOrgsOrganizationProjectsProjectMetricsRoute + '/orgs/$organization/projects/$project/settings': typeof ContextCloudOrgsOrganizationProjectsProjectSettingsRoute '/orgs/$organization/projects/$project/': typeof ContextCloudOrgsOrganizationProjectsProjectIndexRoute '/orgs/$organization/projects/$project/ns/$namespace': typeof ContextCloudOrgsOrganizationProjectsProjectNsNamespaceRouteWithChildren '/orgs/$organization/projects/$project/ns/$namespace/billing': typeof ContextCloudOrgsOrganizationProjectsProjectNsNamespaceBillingRoute @@ -281,6 +289,7 @@ export interface FileRoutesByTo { '/orgs/$organization/projects': typeof ContextCloudOrgsOrganizationProjectsIndexRoute '/orgs/$organization/projects/$project/billing': typeof ContextCloudOrgsOrganizationProjectsProjectBillingRoute '/orgs/$organization/projects/$project/metrics': typeof ContextCloudOrgsOrganizationProjectsProjectMetricsRoute + '/orgs/$organization/projects/$project/settings': typeof ContextCloudOrgsOrganizationProjectsProjectSettingsRoute '/orgs/$organization/projects/$project': typeof ContextCloudOrgsOrganizationProjectsProjectIndexRoute '/orgs/$organization/projects/$project/ns/$namespace/billing': typeof ContextCloudOrgsOrganizationProjectsProjectNsNamespaceBillingRoute '/orgs/$organization/projects/$project/ns/$namespace/connect': typeof ContextCloudOrgsOrganizationProjectsProjectNsNamespaceConnectRoute @@ -314,6 +323,7 @@ export interface FileRoutesById { '/_context/_cloud/orgs/$organization/projects/': typeof ContextCloudOrgsOrganizationProjectsIndexRoute '/_context/_cloud/orgs/$organization/projects/$project/billing': typeof ContextCloudOrgsOrganizationProjectsProjectBillingRoute '/_context/_cloud/orgs/$organization/projects/$project/metrics': typeof ContextCloudOrgsOrganizationProjectsProjectMetricsRoute + '/_context/_cloud/orgs/$organization/projects/$project/settings': typeof ContextCloudOrgsOrganizationProjectsProjectSettingsRoute '/_context/_cloud/orgs/$organization/projects/$project/': typeof ContextCloudOrgsOrganizationProjectsProjectIndexRoute '/_context/_cloud/orgs/$organization/projects/$project/ns/$namespace': typeof ContextCloudOrgsOrganizationProjectsProjectNsNamespaceRouteWithChildren '/_context/_cloud/orgs/$organization/projects/$project/ns/$namespace/billing': typeof ContextCloudOrgsOrganizationProjectsProjectNsNamespaceBillingRoute @@ -346,6 +356,7 @@ export interface FileRouteTypes { | '/orgs/$organization/projects' | '/orgs/$organization/projects/$project/billing' | '/orgs/$organization/projects/$project/metrics' + | '/orgs/$organization/projects/$project/settings' | '/orgs/$organization/projects/$project/' | '/orgs/$organization/projects/$project/ns/$namespace' | '/orgs/$organization/projects/$project/ns/$namespace/billing' @@ -373,6 +384,7 @@ export interface FileRouteTypes { | '/orgs/$organization/projects' | '/orgs/$organization/projects/$project/billing' | '/orgs/$organization/projects/$project/metrics' + | '/orgs/$organization/projects/$project/settings' | '/orgs/$organization/projects/$project' | '/orgs/$organization/projects/$project/ns/$namespace/billing' | '/orgs/$organization/projects/$project/ns/$namespace/connect' @@ -405,6 +417,7 @@ export interface FileRouteTypes { | '/_context/_cloud/orgs/$organization/projects/' | '/_context/_cloud/orgs/$organization/projects/$project/billing' | '/_context/_cloud/orgs/$organization/projects/$project/metrics' + | '/_context/_cloud/orgs/$organization/projects/$project/settings' | '/_context/_cloud/orgs/$organization/projects/$project/' | '/_context/_cloud/orgs/$organization/projects/$project/ns/$namespace' | '/_context/_cloud/orgs/$organization/projects/$project/ns/$namespace/billing' @@ -579,6 +592,13 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof ContextCloudOrgsOrganizationProjectsProjectIndexRouteImport parentRoute: typeof ContextCloudOrgsOrganizationProjectsProjectRoute } + '/_context/_cloud/orgs/$organization/projects/$project/settings': { + id: '/_context/_cloud/orgs/$organization/projects/$project/settings' + path: '/settings' + fullPath: '/orgs/$organization/projects/$project/settings' + preLoaderRoute: typeof ContextCloudOrgsOrganizationProjectsProjectSettingsRouteImport + parentRoute: typeof ContextCloudOrgsOrganizationProjectsProjectRoute + } '/_context/_cloud/orgs/$organization/projects/$project/metrics': { id: '/_context/_cloud/orgs/$organization/projects/$project/metrics' path: '/metrics' @@ -678,6 +698,7 @@ const ContextCloudOrgsOrganizationProjectsProjectNsNamespaceRouteWithChildren = interface ContextCloudOrgsOrganizationProjectsProjectRouteChildren { ContextCloudOrgsOrganizationProjectsProjectBillingRoute: typeof ContextCloudOrgsOrganizationProjectsProjectBillingRoute ContextCloudOrgsOrganizationProjectsProjectMetricsRoute: typeof ContextCloudOrgsOrganizationProjectsProjectMetricsRoute + ContextCloudOrgsOrganizationProjectsProjectSettingsRoute: typeof ContextCloudOrgsOrganizationProjectsProjectSettingsRoute ContextCloudOrgsOrganizationProjectsProjectIndexRoute: typeof ContextCloudOrgsOrganizationProjectsProjectIndexRoute ContextCloudOrgsOrganizationProjectsProjectNsNamespaceRoute: typeof ContextCloudOrgsOrganizationProjectsProjectNsNamespaceRouteWithChildren } @@ -688,6 +709,8 @@ const ContextCloudOrgsOrganizationProjectsProjectRouteChildren: ContextCloudOrgs ContextCloudOrgsOrganizationProjectsProjectBillingRoute, ContextCloudOrgsOrganizationProjectsProjectMetricsRoute: ContextCloudOrgsOrganizationProjectsProjectMetricsRoute, + ContextCloudOrgsOrganizationProjectsProjectSettingsRoute: + ContextCloudOrgsOrganizationProjectsProjectSettingsRoute, ContextCloudOrgsOrganizationProjectsProjectIndexRoute: ContextCloudOrgsOrganizationProjectsProjectIndexRoute, ContextCloudOrgsOrganizationProjectsProjectNsNamespaceRoute: diff --git a/frontend/src/routes/_context/_cloud.tsx b/frontend/src/routes/_context/_cloud.tsx index 5aafbc7b21..ae097e629e 100644 --- a/frontend/src/routes/_context/_cloud.tsx +++ b/frontend/src/routes/_context/_cloud.tsx @@ -47,6 +47,8 @@ function CloudModals() { const ConnectHetznerDialog = useDialog.ConnectHetzner.Dialog; const EditProviderConfigDialog = useDialog.EditProviderConfig.Dialog; const DeleteConfigDialog = useDialog.DeleteConfig.Dialog; + const DeleteNamespaceDialog = useDialog.DeleteNamespace.Dialog; + const DeleteProjectDialog = useDialog.DeleteProject.Dialog; const CreateOrganizationDialog = useDialog.CreateOrganization.Dialog; return ( @@ -291,6 +293,42 @@ function CloudModals() { }, }} /> + { + if (!value) { + navigate({ + to: ".", + search: (old) => ({ + ...old, + modal: undefined, + displayName: undefined, + }), + }); + } + }, + }} + /> + { + if (!value) { + navigate({ + to: ".", + search: (old) => ({ + ...old, + modal: undefined, + displayName: undefined, + }), + }); + } + }, + }} + /> {__APP_TYPE__ === "cloud" ? : null} + {__APP_TYPE__ === "cloud" ? : null} @@ -409,3 +412,78 @@ function DatacenterStatus() { ); } + +function DangerZone() { + const dataProvider = useCloudNamespaceDataProvider(); + const navigate = useNavigate(); + + const { data: project } = useQuery( + dataProvider.currentProjectQueryOptions(), + ); + + const { data: namespace } = useQuery( + dataProvider.currentNamespaceQueryOptions(), + ); + + return ( +
+
+

Danger Zone

+
+

+ Perform actions that could affect the stability of your Rivet + Actors and Runners. +

+ +
+

+ Archive namespace '{namespace?.displayName}' +

+

+ Archiving this namespace will permanently remove all + associated Rivet Actors, Runners, and configurations. This + action cannot be undone. +

+ +
+ +
+

+ Archive project '{project?.displayName}' +

+

+ Archiving this project will permanently remove all + associated Rivet Actors, Runners, and configurations. This + action cannot be undone. +

+ +
+
+ ); +} diff --git a/frontend/src/routes/_context/_cloud/orgs.$organization/projects.$project/settings.tsx b/frontend/src/routes/_context/_cloud/orgs.$organization/projects.$project/settings.tsx new file mode 100644 index 0000000000..b340de6ed2 --- /dev/null +++ b/frontend/src/routes/_context/_cloud/orgs.$organization/projects.$project/settings.tsx @@ -0,0 +1,96 @@ +import { faQuestionCircle, Icon } from "@rivet-gg/icons"; +import { useQuery } from "@tanstack/react-query"; +import { createFileRoute, notFound, useNavigate } from "@tanstack/react-router"; +import { match } from "ts-pattern"; +import { HelpDropdown } from "@/app/help-dropdown"; +import { Content } from "@/app/layout"; +import { RouteLayout } from "@/app/route-layout"; +import { SidebarToggle } from "@/app/sidebar-toggle"; +import { Button, H1, H3, H4 } from "@/components"; +import { useCloudProjectDataProvider } from "@/components/actors"; + +export const Route = createFileRoute( + "/_context/_cloud/orgs/$organization/projects/$project/settings", +)({ + component: match(__APP_TYPE__) + .with("cloud", () => RouteComponent) + .otherwise(() => () => { + throw notFound(); + }), +}); + +function RouteComponent() { + return ( + + +
+
+
+ +

Project Settings

+ + + +
+
+ +
+ +
+ +
+
+
+
+ ); +} + +function DangerZone() { + const dataProvider = useCloudProjectDataProvider(); + const navigate = useNavigate(); + + const { data: project } = useQuery( + dataProvider.currentProjectQueryOptions(), + ); + + return ( +
+
+

Danger Zone

+
+

+ Perform actions that could affect the stability of your project. +

+ +
+

+ Archive project '{project?.displayName}' +

+

+ Archiving this project will permanently remove all associated + namespaces, Rivet Actors, Runners, and configurations. This + action cannot be undone. +

+ +
+
+ ); +} diff --git a/package.json b/package.json index 828717f8c8..75d2d2b470 100644 --- a/package.json +++ b/package.json @@ -45,7 +45,7 @@ "overrides": { "react": "19.1.0", "react-dom": "19.1.0", - "@rivet-gg/cloud": "https://pkg.pr.new/rivet-dev/cloud/@rivet-gg/cloud@2243d29", + "@rivet-gg/cloud": "https://pkg.pr.new/rivet-dev/cloud/@rivet-gg/cloud@edc6ad0", "@codemirror/state": "^6.5.2" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b0570289b6..80de795a85 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -16,7 +16,7 @@ overrides: '@clerk/shared': 3.27.1 react: 19.1.0 react-dom: 19.1.0 - '@rivet-gg/cloud': https://pkg.pr.new/rivet-dev/cloud/@rivet-gg/cloud@2243d29 + '@rivet-gg/cloud': https://pkg.pr.new/rivet-dev/cloud/@rivet-gg/cloud@edc6ad0 '@codemirror/state': ^6.5.2 importers: @@ -465,8 +465,8 @@ importers: specifier: ^4.7.0 version: 4.7.0(monaco-editor@0.55.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@rivet-gg/cloud': - specifier: https://pkg.pr.new/rivet-dev/cloud/@rivet-gg/cloud@2243d29 - version: https://pkg.pr.new/rivet-dev/cloud/@rivet-gg/cloud@2243d29 + specifier: https://pkg.pr.new/rivet-dev/cloud/@rivet-gg/cloud@edc6ad0 + version: https://pkg.pr.new/rivet-dev/cloud/@rivet-gg/cloud@edc6ad0 '@rivetkit/engine-api-full': specifier: workspace:* version: link:../../engine/sdks/typescript/api-full @@ -3048,8 +3048,8 @@ importers: specifier: ^1.2.3 version: 1.2.3(@types/react-dom@19.2.2(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@rivet-gg/cloud': - specifier: https://pkg.pr.new/rivet-dev/cloud/@rivet-gg/cloud@2243d29 - version: https://pkg.pr.new/rivet-dev/cloud/@rivet-gg/cloud@2243d29 + specifier: https://pkg.pr.new/rivet-dev/cloud/@rivet-gg/cloud@edc6ad0 + version: https://pkg.pr.new/rivet-dev/cloud/@rivet-gg/cloud@edc6ad0 '@rivet-gg/icons': specifier: workspace:* version: link:packages/icons @@ -3425,7 +3425,7 @@ importers: version: 3.13.12(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@uiw/codemirror-extensions-basic-setup': specifier: ^4.25.1 - version: 4.25.1(@codemirror/autocomplete@6.19.0)(@codemirror/commands@6.9.0)(@codemirror/language@6.11.3)(@codemirror/lint@6.9.0)(@codemirror/search@6.5.11)(@codemirror/state@6.5.2)(@codemirror/view@6.38.2) + version: 4.25.1(@codemirror/autocomplete@6.19.0)(@codemirror/commands@6.8.1)(@codemirror/language@6.11.3)(@codemirror/lint@6.9.0)(@codemirror/search@6.5.11)(@codemirror/state@6.5.2)(@codemirror/view@6.38.2) '@uiw/codemirror-theme-github': specifier: ^4.25.1 version: 4.25.1(@codemirror/language@6.11.3)(@codemirror/state@6.5.2)(@codemirror/view@6.38.2) @@ -4072,6 +4072,9 @@ importers: '@types/node': specifier: ^24.3.1 version: 24.3.1 + tsx: + specifier: ^4.20.5 + version: 4.20.6 shared/typescript/virtual-websocket: devDependencies: @@ -4124,8 +4127,8 @@ importers: specifier: 25.5.3 version: 25.5.3 '@rivet-gg/cloud': - specifier: https://pkg.pr.new/rivet-dev/cloud/@rivet-gg/cloud@2243d29 - version: https://pkg.pr.new/rivet-dev/cloud/@rivet-gg/cloud@2243d29 + specifier: https://pkg.pr.new/rivet-dev/cloud/@rivet-gg/cloud@edc6ad0 + version: https://pkg.pr.new/rivet-dev/cloud/@rivet-gg/cloud@edc6ad0 '@rivet-gg/components': specifier: workspace:* version: link:../frontend/packages/components @@ -8424,8 +8427,8 @@ packages: '@rivet-gg/api@25.5.3': resolution: {integrity: sha512-pj8xYQ+I/aQDbThmicPxvR+TWAzGoLSE53mbJi4QZHF8VH2oMvU7CMWqy7OTFH30DIRyVzsnHHRJZKGwtmQL3g==} - '@rivet-gg/cloud@https://pkg.pr.new/rivet-dev/cloud/@rivet-gg/cloud@2243d29': - resolution: {tarball: https://pkg.pr.new/rivet-dev/cloud/@rivet-gg/cloud@2243d29} + '@rivet-gg/cloud@https://pkg.pr.new/rivet-dev/cloud/@rivet-gg/cloud@edc6ad0': + resolution: {tarball: https://pkg.pr.new/rivet-dev/cloud/@rivet-gg/cloud@edc6ad0} version: 0.0.0 '@rivetkit/bare-ts@0.6.2': @@ -20215,7 +20218,7 @@ snapshots: react-simple-code-editor: 0.14.1(react-dom@19.1.0(react@19.1.0))(react@19.1.0) serve-handler: 6.1.6 tailwind-merge: 2.6.0 - tailwindcss-animate: 1.0.7(tailwindcss@3.4.17(ts-node@10.9.2(@types/node@20.19.13)(typescript@5.9.3))) + tailwindcss-animate: 1.0.7(tailwindcss@3.4.17(ts-node@10.9.2(@types/node@20.19.13)(typescript@5.9.2))) zod: 3.25.76 transitivePeerDependencies: - '@cfworker/json-schema' @@ -21426,7 +21429,7 @@ snapshots: transitivePeerDependencies: - encoding - '@rivet-gg/cloud@https://pkg.pr.new/rivet-dev/cloud/@rivet-gg/cloud@2243d29': + '@rivet-gg/cloud@https://pkg.pr.new/rivet-dev/cloud/@rivet-gg/cloud@edc6ad0': dependencies: cross-fetch: 4.1.0 form-data: 4.0.5 @@ -22713,16 +22716,6 @@ snapshots: '@codemirror/state': 6.5.2 '@codemirror/view': 6.38.2 - '@uiw/codemirror-extensions-basic-setup@4.25.1(@codemirror/autocomplete@6.19.0)(@codemirror/commands@6.9.0)(@codemirror/language@6.11.3)(@codemirror/lint@6.9.0)(@codemirror/search@6.5.11)(@codemirror/state@6.5.2)(@codemirror/view@6.38.2)': - dependencies: - '@codemirror/autocomplete': 6.19.0 - '@codemirror/commands': 6.9.0 - '@codemirror/language': 6.11.3 - '@codemirror/lint': 6.9.0 - '@codemirror/search': 6.5.11 - '@codemirror/state': 6.5.2 - '@codemirror/view': 6.38.2 - '@uiw/codemirror-theme-github@4.25.1(@codemirror/language@6.11.3)(@codemirror/state@6.5.2)(@codemirror/view@6.38.2)': dependencies: '@uiw/codemirror-themes': 4.25.1(@codemirror/language@6.11.3)(@codemirror/state@6.5.2)(@codemirror/view@6.38.2) diff --git a/rivetkit-typescript/packages/cloudflare-workers/src/config.ts b/rivetkit-typescript/packages/cloudflare-workers/src/config.ts index 8d502a6cdb..d30139cf02 100644 --- a/rivetkit-typescript/packages/cloudflare-workers/src/config.ts +++ b/rivetkit-typescript/packages/cloudflare-workers/src/config.ts @@ -1,5 +1,5 @@ import type { Client } from "rivetkit"; -import { z } from "zod"; +import { z } from "zod/v4"; const ConfigSchemaBase = z.object({ /** Path that the Rivet manager API will be mounted. */ diff --git a/rivetkit-typescript/packages/rivetkit/src/actor/config.ts b/rivetkit-typescript/packages/rivetkit/src/actor/config.ts index 567dc6c30c..9340815294 100644 --- a/rivetkit-typescript/packages/rivetkit/src/actor/config.ts +++ b/rivetkit-typescript/packages/rivetkit/src/actor/config.ts @@ -1,4 +1,4 @@ -import { z } from "zod"; +import { z } from "zod/v4"; import type { UniversalWebSocket } from "@/common/websocket-interface"; import type { Conn } from "./conn/mod"; import type { diff --git a/rivetkit-typescript/packages/rivetkit/src/actor/protocol/old.ts b/rivetkit-typescript/packages/rivetkit/src/actor/protocol/old.ts index cea51afbde..5a6654f684 100644 --- a/rivetkit-typescript/packages/rivetkit/src/actor/protocol/old.ts +++ b/rivetkit-typescript/packages/rivetkit/src/actor/protocol/old.ts @@ -1,5 +1,5 @@ import * as cbor from "cbor-x"; -import { z } from "zod"; +import { z } from "zod/v4"; import type { AnyDatabaseProvider } from "@/actor/database"; import * as errors from "@/actor/errors"; import { diff --git a/rivetkit-typescript/packages/rivetkit/src/actor/protocol/serde.ts b/rivetkit-typescript/packages/rivetkit/src/actor/protocol/serde.ts index f86e347656..045a637d36 100644 --- a/rivetkit-typescript/packages/rivetkit/src/actor/protocol/serde.ts +++ b/rivetkit-typescript/packages/rivetkit/src/actor/protocol/serde.ts @@ -1,6 +1,6 @@ import * as cbor from "cbor-x"; import type { VersionedDataHandler } from "vbare"; -import { z } from "zod"; +import { z } from "zod/v4"; import * as errors from "@/actor/errors"; import { serializeWithEncoding } from "@/serde"; import { loggerWithoutContext } from "../log"; diff --git a/rivetkit-typescript/packages/rivetkit/src/client/config.ts b/rivetkit-typescript/packages/rivetkit/src/client/config.ts index 721c7900be..f6242c39b6 100644 --- a/rivetkit-typescript/packages/rivetkit/src/client/config.ts +++ b/rivetkit-typescript/packages/rivetkit/src/client/config.ts @@ -1,4 +1,4 @@ -import z from "zod"; +import z from "zod/v4"; import { EncodingSchema } from "@/actor/protocol/serde"; import { type GetUpgradeWebSocket } from "@/utils"; import { diff --git a/rivetkit-typescript/packages/rivetkit/src/client/utils.ts b/rivetkit-typescript/packages/rivetkit/src/client/utils.ts index f518d69e92..c4d61f02e4 100644 --- a/rivetkit-typescript/packages/rivetkit/src/client/utils.ts +++ b/rivetkit-typescript/packages/rivetkit/src/client/utils.ts @@ -1,7 +1,7 @@ import * as cbor from "cbor-x"; import invariant from "invariant"; import type { VersionedDataHandler } from "vbare"; -import type { z } from "zod"; +import type { z } from "zod/v4"; import type { Encoding } from "@/actor/protocol/serde"; import { assertUnreachable } from "@/common/utils"; import type { HttpResponseError } from "@/schemas/client-protocol/mod"; diff --git a/rivetkit-typescript/packages/rivetkit/src/common/log.ts b/rivetkit-typescript/packages/rivetkit/src/common/log.ts index 6a09091b87..62dd7003d6 100644 --- a/rivetkit-typescript/packages/rivetkit/src/common/log.ts +++ b/rivetkit-typescript/packages/rivetkit/src/common/log.ts @@ -4,7 +4,7 @@ import { pino, stdTimeFunctions, } from "pino"; -import { z } from "zod"; +import { z } from "zod/v4"; import { getLogLevel, getLogTarget, getLogTimestamp } from "@/utils/env-vars"; import { castToLogValue, diff --git a/rivetkit-typescript/packages/rivetkit/src/driver-test-suite/tests/raw-http-request-properties.ts b/rivetkit-typescript/packages/rivetkit/src/driver-test-suite/tests/raw-http-request-properties.ts index cdf258880d..522af066a4 100644 --- a/rivetkit-typescript/packages/rivetkit/src/driver-test-suite/tests/raw-http-request-properties.ts +++ b/rivetkit-typescript/packages/rivetkit/src/driver-test-suite/tests/raw-http-request-properties.ts @@ -1,5 +1,5 @@ import { describe, expect, test } from "vitest"; -import { z } from "zod"; +import { z } from "zod/v4"; import { registry } from "../../../fixtures/driver-test-suite/registry"; import type { DriverTestConfig } from "../mod"; import { setupDriverTest } from "../utils"; diff --git a/rivetkit-typescript/packages/rivetkit/src/drivers/engine/config.ts b/rivetkit-typescript/packages/rivetkit/src/drivers/engine/config.ts index 6720c50ba4..e1620534ff 100644 --- a/rivetkit-typescript/packages/rivetkit/src/drivers/engine/config.ts +++ b/rivetkit-typescript/packages/rivetkit/src/drivers/engine/config.ts @@ -1,4 +1,4 @@ -import { z } from "zod"; +import { z } from "zod/v4"; import { ClientConfigSchemaBase, transformClientConfig, diff --git a/rivetkit-typescript/packages/rivetkit/src/inspector/config.ts b/rivetkit-typescript/packages/rivetkit/src/inspector/config.ts index 8ecb692054..9db05ec2e0 100644 --- a/rivetkit-typescript/packages/rivetkit/src/inspector/config.ts +++ b/rivetkit-typescript/packages/rivetkit/src/inspector/config.ts @@ -1,4 +1,4 @@ -import { z } from "zod"; +import { z } from "zod/v4"; import { getRivetkitInspectorToken, isDev, diff --git a/rivetkit-typescript/packages/rivetkit/src/inspector/handler.ts b/rivetkit-typescript/packages/rivetkit/src/inspector/handler.ts index 5b8cae8e7b..ca10f33933 100644 --- a/rivetkit-typescript/packages/rivetkit/src/inspector/handler.ts +++ b/rivetkit-typescript/packages/rivetkit/src/inspector/handler.ts @@ -3,7 +3,7 @@ import type { Unsubscribe } from "nanoevents"; import type { UpgradeWebSocketArgs } from "@/actor/router-websocket-endpoints"; import type { AnyActorInstance, RivetMessageEvent } from "@/mod"; import type { ToClient } from "@/schemas/actor-inspector/mod"; -import { encodeReadRangeWire } from "@rivetkit/traces"; +import { encodeReadRangeWire } from "@rivetkit/traces/encoding"; import { CURRENT_VERSION as INSPECTOR_CURRENT_VERSION, TO_CLIENT_VERSIONED as toClient, diff --git a/rivetkit-typescript/packages/rivetkit/src/manager-api/actors.ts b/rivetkit-typescript/packages/rivetkit/src/manager-api/actors.ts index e5bd42290e..b92b87273b 100644 --- a/rivetkit-typescript/packages/rivetkit/src/manager-api/actors.ts +++ b/rivetkit-typescript/packages/rivetkit/src/manager-api/actors.ts @@ -1,4 +1,4 @@ -import { z } from "zod"; +import { z } from "zod/v4"; import { RivetIdSchema } from "./common"; export const ActorSchema = z.object({ diff --git a/rivetkit-typescript/packages/rivetkit/src/manager-api/common.ts b/rivetkit-typescript/packages/rivetkit/src/manager-api/common.ts index f74e6c217b..e4718c6fca 100644 --- a/rivetkit-typescript/packages/rivetkit/src/manager-api/common.ts +++ b/rivetkit-typescript/packages/rivetkit/src/manager-api/common.ts @@ -1,4 +1,4 @@ -import { z } from "zod"; +import { z } from "zod/v4"; export const RivetIdSchema = z.string(); export type RivetId = z.infer; diff --git a/rivetkit-typescript/packages/rivetkit/src/manager/protocol/mod.ts b/rivetkit-typescript/packages/rivetkit/src/manager/protocol/mod.ts index 13343c3dd2..c0dba4b466 100644 --- a/rivetkit-typescript/packages/rivetkit/src/manager/protocol/mod.ts +++ b/rivetkit-typescript/packages/rivetkit/src/manager/protocol/mod.ts @@ -1,4 +1,4 @@ -import { z } from "zod"; +import { z } from "zod/v4"; import { ActorQuerySchema } from "./query"; export * from "./query"; diff --git a/rivetkit-typescript/packages/rivetkit/src/manager/protocol/query.ts b/rivetkit-typescript/packages/rivetkit/src/manager/protocol/query.ts index bd887b2b53..f7dc9a1eda 100644 --- a/rivetkit-typescript/packages/rivetkit/src/manager/protocol/query.ts +++ b/rivetkit-typescript/packages/rivetkit/src/manager/protocol/query.ts @@ -1,4 +1,4 @@ -import { z } from "zod"; +import { z } from "zod/v4"; import { EncodingSchema } from "@/actor/protocol/serde"; import { HEADER_ACTOR_ID, diff --git a/rivetkit-typescript/packages/rivetkit/src/manager/router-schema.ts b/rivetkit-typescript/packages/rivetkit/src/manager/router-schema.ts index afef03772c..cc29e62db6 100644 --- a/rivetkit-typescript/packages/rivetkit/src/manager/router-schema.ts +++ b/rivetkit-typescript/packages/rivetkit/src/manager/router-schema.ts @@ -1,4 +1,4 @@ -import { z } from "zod"; +import { z } from "zod/v4"; export const ServerlessStartHeadersSchema = z.object({ endpoint: z.string({ diff --git a/rivetkit-typescript/packages/rivetkit/src/manager/router.ts b/rivetkit-typescript/packages/rivetkit/src/manager/router.ts index 6f83c788f9..7e44860a41 100644 --- a/rivetkit-typescript/packages/rivetkit/src/manager/router.ts +++ b/rivetkit-typescript/packages/rivetkit/src/manager/router.ts @@ -3,7 +3,7 @@ import * as cbor from "cbor-x"; import type { Hono } from "hono"; import invariant from "invariant"; -import { z } from "zod"; +import { z } from "zod/v4"; import { Forbidden, RestrictedFeature } from "@/actor/errors"; import { serializeActorKey } from "@/actor/keys"; diff --git a/rivetkit-typescript/packages/rivetkit/src/registry/config/driver.ts b/rivetkit-typescript/packages/rivetkit/src/registry/config/driver.ts index bc1e2bf04f..7f0f0712a4 100644 --- a/rivetkit-typescript/packages/rivetkit/src/registry/config/driver.ts +++ b/rivetkit-typescript/packages/rivetkit/src/registry/config/driver.ts @@ -1,4 +1,4 @@ -import { z } from "zod"; +import { z } from "zod/v4"; import { ActorDriverBuilder } from "@/actor/driver"; import { ManagerDriverBuilder } from "@/manager/driver"; diff --git a/rivetkit-typescript/packages/rivetkit/src/registry/config/index.ts b/rivetkit-typescript/packages/rivetkit/src/registry/config/index.ts index 1c0519755f..40c1b055d3 100644 --- a/rivetkit-typescript/packages/rivetkit/src/registry/config/index.ts +++ b/rivetkit-typescript/packages/rivetkit/src/registry/config/index.ts @@ -1,4 +1,4 @@ -import { z } from "zod"; +import { z } from "zod/v4"; import type { ActorDefinition, AnyActorDefinition } from "@/actor/definition"; import { getRunMetadata } from "@/actor/config"; import { type Logger, LogLevelSchema } from "@/common/log"; diff --git a/rivetkit-typescript/packages/rivetkit/src/registry/config/legacy-runner.ts b/rivetkit-typescript/packages/rivetkit/src/registry/config/legacy-runner.ts index 652befe45e..7aabeea402 100644 --- a/rivetkit-typescript/packages/rivetkit/src/registry/config/legacy-runner.ts +++ b/rivetkit-typescript/packages/rivetkit/src/registry/config/legacy-runner.ts @@ -1,5 +1,5 @@ import type { Logger } from "pino"; -import { z } from "zod"; +import { z } from "zod/v4"; import type { ActorDriverBuilder } from "@/actor/driver"; import { LogLevelSchema } from "@/common/log"; import { diff --git a/rivetkit-typescript/packages/rivetkit/src/registry/config/runner.ts b/rivetkit-typescript/packages/rivetkit/src/registry/config/runner.ts index ee3ccd209e..6fe7abc933 100644 --- a/rivetkit-typescript/packages/rivetkit/src/registry/config/runner.ts +++ b/rivetkit-typescript/packages/rivetkit/src/registry/config/runner.ts @@ -1,4 +1,4 @@ -import { z } from "zod"; +import { z } from "zod/v4"; import { isDev, getRivetTotalSlots, diff --git a/rivetkit-typescript/packages/rivetkit/src/registry/config/serverless.ts b/rivetkit-typescript/packages/rivetkit/src/registry/config/serverless.ts index 0351674027..5d2e689433 100644 --- a/rivetkit-typescript/packages/rivetkit/src/registry/config/serverless.ts +++ b/rivetkit-typescript/packages/rivetkit/src/registry/config/serverless.ts @@ -1,4 +1,4 @@ -import { z } from "zod"; +import { z } from "zod/v4"; import { VERSION } from "@/utils"; import { getRivetRunEngineVersion, diff --git a/rivetkit-typescript/packages/rivetkit/src/remote-manager-driver/api-utils.ts b/rivetkit-typescript/packages/rivetkit/src/remote-manager-driver/api-utils.ts index 2c41c0aabd..4bca135b33 100644 --- a/rivetkit-typescript/packages/rivetkit/src/remote-manager-driver/api-utils.ts +++ b/rivetkit-typescript/packages/rivetkit/src/remote-manager-driver/api-utils.ts @@ -1,4 +1,4 @@ -import { z } from "zod"; +import { z } from "zod/v4"; import type { ClientConfig } from "@/client/config"; import { sendHttpRequest } from "@/client/utils"; import { combineUrlPath } from "@/utils"; diff --git a/rivetkit-typescript/packages/rivetkit/src/schemas/client-protocol-zod/mod.ts b/rivetkit-typescript/packages/rivetkit/src/schemas/client-protocol-zod/mod.ts index c7b798f268..27cba64f43 100644 --- a/rivetkit-typescript/packages/rivetkit/src/schemas/client-protocol-zod/mod.ts +++ b/rivetkit-typescript/packages/rivetkit/src/schemas/client-protocol-zod/mod.ts @@ -1,4 +1,4 @@ -import { z } from "zod"; +import { z } from "zod/v4"; // Helper schemas const UintSchema = z.bigint(); diff --git a/rivetkit-typescript/packages/rivetkit/src/serde.ts b/rivetkit-typescript/packages/rivetkit/src/serde.ts index 2def8d6499..7533a48b36 100644 --- a/rivetkit-typescript/packages/rivetkit/src/serde.ts +++ b/rivetkit-typescript/packages/rivetkit/src/serde.ts @@ -1,7 +1,7 @@ import * as cbor from "cbor-x"; import invariant from "invariant"; import type { VersionedDataHandler } from "vbare"; -import type { z } from "zod"; +import type { z } from "zod/v4"; import { assertUnreachable } from "@/common/utils"; import type { Encoding } from "@/mod"; import { jsonParseCompat, jsonStringifyCompat } from "./actor/protocol/serde"; diff --git a/rivetkit-typescript/packages/rivetkit/src/utils/endpoint-parser.test.ts b/rivetkit-typescript/packages/rivetkit/src/utils/endpoint-parser.test.ts index d4c2e53ab7..d1e2dab30b 100644 --- a/rivetkit-typescript/packages/rivetkit/src/utils/endpoint-parser.test.ts +++ b/rivetkit-typescript/packages/rivetkit/src/utils/endpoint-parser.test.ts @@ -1,5 +1,5 @@ import { describe, expect, test } from "vitest"; -import type { z } from "zod"; +import type { z } from "zod/v4"; import { tryParseEndpoint } from "./endpoint-parser"; // Helper to create a mock Zod refinement context for testing diff --git a/rivetkit-typescript/packages/rivetkit/src/utils/endpoint-parser.ts b/rivetkit-typescript/packages/rivetkit/src/utils/endpoint-parser.ts index 4816a34ec9..b18b94a097 100644 --- a/rivetkit-typescript/packages/rivetkit/src/utils/endpoint-parser.ts +++ b/rivetkit-typescript/packages/rivetkit/src/utils/endpoint-parser.ts @@ -1,4 +1,4 @@ -import { z } from "zod"; +import { z } from "zod/v4"; export interface ParsedEndpoint { endpoint: string; diff --git a/rivetkit-typescript/packages/rivetkit/tsconfig.json b/rivetkit-typescript/packages/rivetkit/tsconfig.json index ed8967e718..75f9f8f734 100644 --- a/rivetkit-typescript/packages/rivetkit/tsconfig.json +++ b/rivetkit-typescript/packages/rivetkit/tsconfig.json @@ -7,6 +7,8 @@ "@/*": ["./src/*"], "@rivetkit/workflow-engine": ["../workflow-engine/src/index.ts"], "@rivetkit/traces": ["../traces/src/index.ts"], + "@rivetkit/traces/encoding": ["../traces/src/encoding.ts"], + "@rivetkit/traces/otlp": ["../traces/src/otlp-entry.ts"], // Used for test fixtures "rivetkit": ["./src/mod.ts"], "rivetkit/utils": ["./src/utils.ts"] diff --git a/rivetkit-typescript/packages/rivetkit/tsup.config.ts b/rivetkit-typescript/packages/rivetkit/tsup.config.ts index e8e9cec121..20b6353efd 100644 --- a/rivetkit-typescript/packages/rivetkit/tsup.config.ts +++ b/rivetkit-typescript/packages/rivetkit/tsup.config.ts @@ -6,6 +6,10 @@ import defaultConfig from "../../../tsup.base.ts"; export default defineConfig({ ...defaultConfig, outDir: "dist/tsup/", + esbuildOptions(options) { + options.external = options.external ?? []; + options.external.push("@rivetkit/traces", "@rivetkit/traces/encoding", "@rivetkit/traces/otlp"); + }, define: { "globalThis.CUSTOM_RIVETKIT_DEVTOOLS_URL": process.env .CUSTOM_RIVETKIT_DEVTOOLS_URL diff --git a/rivetkit-typescript/packages/traces/package.json b/rivetkit-typescript/packages/traces/package.json index 08eab034e0..8935cbd00f 100644 --- a/rivetkit-typescript/packages/traces/package.json +++ b/rivetkit-typescript/packages/traces/package.json @@ -12,6 +12,11 @@ ], "exports": { ".": { + "browser": { + "types": "./dist/tsup/index.browser.d.ts", + "import": "./dist/tsup/index.browser.js", + "require": "./dist/tsup/index.browser.cjs" + }, "import": { "types": "./dist/tsup/index.d.ts", "default": "./dist/tsup/index.js" @@ -21,14 +26,24 @@ "default": "./dist/tsup/index.cjs" } }, - "./reader": { + "./encoding": { + "import": { + "types": "./dist/tsup/encoding.d.ts", + "default": "./dist/tsup/encoding.js" + }, + "require": { + "types": "./dist/tsup/encoding.d.cts", + "default": "./dist/tsup/encoding.cjs" + } + }, + "./otlp": { "import": { - "types": "./dist/tsup/reader.d.ts", - "default": "./dist/tsup/reader.js" + "types": "./dist/tsup/otlp-entry.d.ts", + "default": "./dist/tsup/otlp-entry.js" }, "require": { - "types": "./dist/tsup/reader.d.cts", - "default": "./dist/tsup/reader.cjs" + "types": "./dist/tsup/otlp-entry.d.cts", + "default": "./dist/tsup/otlp-entry.cjs" } } }, @@ -36,15 +51,15 @@ "node": ">=18.0.0" }, "scripts": { - "build": "pnpm run compile:bare && tsup src/index.ts src/reader.ts", + "build": "pnpm run compile:bare && tsup src/index.ts src/index.browser.ts src/encoding.ts src/otlp-entry.ts", "compile:bare": "tsx scripts/compile-bare.ts compile schemas/v1.bare -o dist/schemas/v1.ts", "check-types": "pnpm run compile:bare && tsc --noEmit", "test": "pnpm run compile:bare && vitest run" }, "dependencies": { "@rivetkit/bare-ts": "^0.6.2", - "cbor-x": "^1.6.0", "fdb-tuple": "^1.0.0", + "cbor-x": "^1.6.0", "vbare": "^0.0.4" }, "devDependencies": { diff --git a/rivetkit-typescript/packages/traces/src/encoding.ts b/rivetkit-typescript/packages/traces/src/encoding.ts new file mode 100644 index 0000000000..f1ded1b4e1 --- /dev/null +++ b/rivetkit-typescript/packages/traces/src/encoding.ts @@ -0,0 +1,18 @@ +import { + CURRENT_VERSION, + READ_RANGE_VERSIONED, + type ReadRangeWire, +} from "../schemas/versioned.js"; + +export type { ReadRangeWire }; + +export function encodeReadRangeWire(wire: ReadRangeWire): Uint8Array { + return READ_RANGE_VERSIONED.serializeWithEmbeddedVersion( + wire, + CURRENT_VERSION, + ); +} + +export function decodeReadRangeWire(bytes: Uint8Array): ReadRangeWire { + return READ_RANGE_VERSIONED.deserializeWithEmbeddedVersion(bytes); +} diff --git a/rivetkit-typescript/packages/traces/src/index.browser.ts b/rivetkit-typescript/packages/traces/src/index.browser.ts new file mode 100644 index 0000000000..f93430a885 --- /dev/null +++ b/rivetkit-typescript/packages/traces/src/index.browser.ts @@ -0,0 +1,11 @@ +// Browser stub: createTraces is server-only (uses node:async_hooks, node:crypto, +// fdb-tuple). This module is selected via the "browser" export condition so that +// bundlers like Vite never pull in the real implementation when resolving +// @rivetkit/traces in a browser context. The function is never actually called +// in the browser; it only exists because tsup chunk-splitting may place the +// import in a shared chunk also reached by client code. +export function createTraces(): never { + throw new Error( + "createTraces is not available in the browser. This is a server-only API.", + ); +} diff --git a/rivetkit-typescript/packages/traces/src/index.ts b/rivetkit-typescript/packages/traces/src/index.ts index 9a28d7b501..134e48672f 100644 --- a/rivetkit-typescript/packages/traces/src/index.ts +++ b/rivetkit-typescript/packages/traces/src/index.ts @@ -1,11 +1,6 @@ export { createTraces, } from "./traces.js"; -export { - decodeReadRangeWire, - encodeReadRangeWire, - readRangeWireToOtlp, -} from "./read-range.js"; export type { EndSpanOptions, EventOptions, diff --git a/rivetkit-typescript/packages/traces/src/otlp-entry.ts b/rivetkit-typescript/packages/traces/src/otlp-entry.ts new file mode 100644 index 0000000000..eda0ff93e4 --- /dev/null +++ b/rivetkit-typescript/packages/traces/src/otlp-entry.ts @@ -0,0 +1,18 @@ +export { readRangeWireToOtlp } from "./read-range.js"; +export { + anyValueFromCborBytes, + anyValueFromJs, + base64FromBytes, + hexFromBytes, + type OtlpAnyValue, + type OtlpExportTraceServiceRequestJson, + type OtlpInstrumentationScope, + type OtlpKeyValue, + type OtlpResource, + type OtlpResourceSpans, + type OtlpScopeSpans, + type OtlpSpan, + type OtlpSpanEvent, + type OtlpSpanLink, + type OtlpSpanStatus, +} from "./otlp.js"; diff --git a/rivetkit-typescript/packages/traces/src/read-range.ts b/rivetkit-typescript/packages/traces/src/read-range.ts index 43b25c2d8e..450bbf6e1d 100644 --- a/rivetkit-typescript/packages/traces/src/read-range.ts +++ b/rivetkit-typescript/packages/traces/src/read-range.ts @@ -1,7 +1,5 @@ import { decode as decodeCbor } from "cbor-x"; import { - CURRENT_VERSION, - READ_RANGE_VERSIONED, type Attributes, type Chunk, type ReadRangeWire, @@ -87,17 +85,6 @@ function spanKey(spanId: Uint8Array | SpanId): string { return hexFromBytes(normalizeBytes(spanId)); } -export function encodeReadRangeWire(wire: ReadRangeWire): Uint8Array { - return READ_RANGE_VERSIONED.serializeWithEmbeddedVersion( - wire, - CURRENT_VERSION, - ); -} - -export function decodeReadRangeWire(bytes: Uint8Array): ReadRangeWire { - return READ_RANGE_VERSIONED.deserializeWithEmbeddedVersion(bytes); -} - export function readRangeWireToOtlp( wire: ReadRangeWire, resource?: OtlpResource, diff --git a/rivetkit-typescript/packages/traces/src/reader.ts b/rivetkit-typescript/packages/traces/src/reader.ts deleted file mode 100644 index d7748bff91..0000000000 --- a/rivetkit-typescript/packages/traces/src/reader.ts +++ /dev/null @@ -1,5 +0,0 @@ -export { - decodeReadRangeWire, - encodeReadRangeWire, - readRangeWireToOtlp, -} from "./read-range.js"; diff --git a/rivetkit-typescript/packages/traces/src/traces.ts b/rivetkit-typescript/packages/traces/src/traces.ts index 36c4e80c30..370deecb64 100644 --- a/rivetkit-typescript/packages/traces/src/traces.ts +++ b/rivetkit-typescript/packages/traces/src/traces.ts @@ -1058,10 +1058,7 @@ export function createTraces( chunkId: number; } { const tuple = unpack(Buffer.from(key)) as [number, number, number]; - return { - bucketStartSec: tuple[1], - chunkId: tuple[2], - }; + return { bucketStartSec: tuple[1], chunkId: tuple[2] }; } function buildChunkKey(bucketStartSec: number, chunkId: number): Uint8Array { diff --git a/rivetkit-typescript/packages/workflow-engine/AGENTS.md b/rivetkit-typescript/packages/workflow-engine/AGENTS.md deleted file mode 100644 index cd920e763d..0000000000 --- a/rivetkit-typescript/packages/workflow-engine/AGENTS.md +++ /dev/null @@ -1,9 +0,0 @@ -# Workflow Engine Notes - -## Dirty State Requirements - -- History entries must set `entry.dirty = true` whenever the entry is created or mutated. `flush()` persists dirty entries and clears the flag. -- Entry metadata must set `metadata.dirty = true` whenever metadata fields change. `flush()` persists dirty metadata and clears the flag. -- Name registry writes are tracked by `storage.flushedNameCount`. New names must be registered with `registerName()` before flushing. -- Workflow state/output/error are tracked via `storage.flushedState`, `storage.flushedOutput`, and `storage.flushedError`. Update the fields and call `flush()`; it will write if the value changed. -- `flush()` does not clear workflow output/error keys when values are unset. If you need to clear them, explicitly `driver.delete(buildWorkflowOutputKey())` or `driver.delete(buildWorkflowErrorKey())`. diff --git a/website/public/examples/queue-sandbox/image.png b/website/public/examples/queue-sandbox/image.png new file mode 100644 index 0000000000..0579be1e04 Binary files /dev/null and b/website/public/examples/queue-sandbox/image.png differ