Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

28 changes: 28 additions & 0 deletions rivetkit-typescript/packages/devtools/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# RivetKit DevTools


## Contributing

To contribute to the RivetKit DevTools package, please follow these steps:

1. Set up assets server for the `dist` folder:
```bash
pnpm dlx serve dist
```

2. Set your `CUSTOM_RIVETKIT_DEVTOOLS_URL` environment variable to point to the assets server (default is `http://localhost:3000`):
```bash
export CUSTOM_RIVETKIT_DEVTOOLS_URL=http://localhost:5000
```

This will ensure that the RivetKit will use local devtool assets instead of fetching them from the CDN.

3. In another terminal, run the development build:
```bash
pnpm dev
```

or run the production build:
```bash
pnpm build
```
40 changes: 40 additions & 0 deletions rivetkit-typescript/packages/devtools/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
{
"name": "@rivetkit/devtools",
"private": true,
"version": "2.0.24-rc.1",
"description": "RivetKit DevTools - A set of development tools for RivetKit",
"license": "Apache-2.0",
"keywords": [
"rivetkit"
],
"sideEffects": [
"./dist/chunk-*.js",
"./dist/chunk-*.cjs"
],
"files": [
"dist",
"package.json"
],
"exports": {
".": {
"import": {
"types": "./dist/mod.d.mts",
"default": "./dist/mod.mjs"
},
"require": {
"types": "./dist/mod.d.ts",
"default": "./dist/mod.js"
}
}
},
"scripts": {
"build": "tsup src/mod.ts",
"check-types": "tsc --noEmit"
},
"devDependencies": {
"tsup": "^8.4.0",
"typescript": "^5.5.2",
"rivetkit": "workspace:*"
},
"stableVersion": "0.8.0"
}
9 changes: 9 additions & 0 deletions rivetkit-typescript/packages/devtools/src/globals.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
declare module "*.css" {
const content: string;
export default content;
}

declare module "*.svg" {
const content: string;
export default content;
}
1 change: 1 addition & 0 deletions rivetkit-typescript/packages/devtools/src/icon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
68 changes: 68 additions & 0 deletions rivetkit-typescript/packages/devtools/src/mod.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import svg from "./icon.svg";
import styles from "./styles.css";

declare global {
interface Window {
_rivetkit_devtools_configs?: Array<
Parameters<typeof import("rivetkit/client")["createClient"]>[0]
>;
}
}

const root = document.createElement("div");

root.id = "rivetkit-devtools";
const shadow = root.attachShadow({ mode: "open" });

const div = document.createElement("div");

const img = document.createElement("img");
img.src = svg;
div.appendChild(img);

const btn = document.createElement("button");
btn.appendChild(div);

const tooltip = document.createElement("div");
tooltip.className = "tooltip";
tooltip.textContent = "Open Inspector";

const style = document.createElement("style");
style.textContent = styles;
shadow.appendChild(style);
shadow.appendChild(btn);
shadow.appendChild(tooltip);

btn.addEventListener("mouseenter", () => {
tooltip.classList.add("visible");
});

btn.addEventListener("mouseleave", () => {
tooltip.classList.remove("visible");
});

btn.addEventListener("click", () => {
const config = window._rivetkit_devtools_configs?.[0];
if (!config || typeof config !== "object") {
console.error("RivetKit Devtools: No client config found");
return;
}
const url = new URL("https://inspect.rivet.dev/");
if (!config.endpoint) {
console.error("RivetKit Devtools: No endpoint found in client config");
return;
}
url.searchParams.set("u", config.endpoint);
if (config.token) {
url.searchParams.set("t", config.token);
}
if (config.namespace) {
url.searchParams.set("ns", config.namespace);
}
if (config.runnerName) {
url.searchParams.set("r", config.runnerName);
}
window.open(url.toString(), "_blank");
});

document.body.appendChild(root);
81 changes: 81 additions & 0 deletions rivetkit-typescript/packages/devtools/src/styles.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
:host {
all: initial;
position: fixed;
bottom: 12px;
right: 25px;
bottom: 25px;
z-index: 2147483647;
width: 48px;
height: 48px;
}

:host * {
box-sizing: border-box;
}

button {
all: unset;
width: 100%;
height: 100%;
cursor: pointer;
border-radius: 50%;
border: 1px solid #171717;
background-color: #09090b;
transition: background-color .3s ease;
}

button:hover {
background-color: #0e0e11;
}

button div {
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
border-radius: 50%;
border: 1px solid #292525;
}

img {
width: 28px;
height: 28px;
object-fit: contain;
}

.tooltip {
position: absolute;
right: 60px;
bottom: 50%;
transform: translateY(50%);
background-color: #09090b;
color: #fafafa;
padding: 6px 12px;
border-radius: 6px;
font-size: 12px;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
white-space: nowrap;
pointer-events: none;
opacity: 0;
transition: opacity .3s ease;
border: 1px solid #27272a;
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.3), 0 2px 4px -1px rgba(0, 0, 0, 0.2);
}

.tooltip::after {
content: "";
position: absolute;
right: -5px;
top: 50%;
transform: translateY(-50%) rotate(45deg);
width: 8px;
height: 8px;
background-color: #09090b;
border-right: 1px solid #27272a;
border-top: 1px solid #27272a;
}

.tooltip.visible {
opacity: 1;
}
24 changes: 24 additions & 0 deletions rivetkit-typescript/packages/devtools/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"compilerOptions": {
"target": "ES2020",
"useDefineForClassFields": true,
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"module": "ESNext",
"skipLibCheck": true,

/* Bundler mode */
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx",

/* Linting */
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true
},
"include": ["src", "lib"]
}
10 changes: 10 additions & 0 deletions rivetkit-typescript/packages/devtools/tsup.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { defineConfig } from "tsup";
import defaultConfig from "../../../tsup.base.ts";

export default defineConfig({
...defaultConfig,
loader: {
".svg": "dataurl",
".css": "text",
},
});
15 changes: 15 additions & 0 deletions rivetkit-typescript/packages/devtools/turbo.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"$schema": "https://turbo.build/schema.json",
"extends": ["//"],
"tasks": {
"build": {
"inputs": [
"src/**",
"tsconfig.json",
"tsup.config.ts",
"package.json"
],
"outputs": ["dist/**"]
}
}
}
9 changes: 9 additions & 0 deletions rivetkit-typescript/packages/rivetkit/src/client/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,15 @@ export const ClientConfigSchema = z.object({

/** Whether to automatically perform health checks when the client is created. */
disableMetadataLookup: z.boolean().optional().default(false),

/** Whether to enable RivetKit Devtools integration. */
devtools: z
.boolean()
.default(
() =>
typeof globalThis.window !== "undefined" &&
window?.location?.hostname === "localhost",
),
});

export type ClientConfig = z.infer<typeof ClientConfigSchema>;
Expand Down
6 changes: 6 additions & 0 deletions rivetkit-typescript/packages/rivetkit/src/client/mod.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { injectDevtools } from "@/devtools/mod";
import type { Registry } from "@/registry/mod";
import { RemoteManagerDriver } from "@/remote-manager-driver/mod";
import {
Expand Down Expand Up @@ -55,5 +56,10 @@ export function createClient<A extends Registry<any>>(

// Create client
const driver = new RemoteManagerDriver(config);

if (config.devtools) {
injectDevtools(config);
}

return createClientWithDriver<A>(driver, config);
}
Loading
Loading