-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
55e070b
commit fefe796
Showing
21 changed files
with
903 additions
and
36 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"rpc-anywhere": patch | ||
--- | ||
|
||
Better naming for low-level message types. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"rpc-anywhere": minor | ||
--- | ||
|
||
Fixed message port transport. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"rpc-anywhere": minor | ||
--- | ||
|
||
Added debug hooks for logging and debugging. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"rpc-anywhere": patch | ||
--- | ||
|
||
Reduced chance of colision for the transport id key. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"rpc-anywhere": minor | ||
--- | ||
|
||
Added a cool demo! |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
*.js | ||
style.css |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
<!doctype html> | ||
<html class="overflow-hidden"> | ||
<head> | ||
<title>RPC Anywhere demo - iframe</title> | ||
<meta charset="UTF-8" /> | ||
<meta name="viewport" content="width=device-width, initial-scale=1" /> | ||
<link rel="preconnect" href="https://fonts.googleapis.com" /> | ||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin /> | ||
<link | ||
href="https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap" | ||
rel="stylesheet" | ||
/> | ||
<link rel="stylesheet" href="/style.css" /> | ||
</head> | ||
<body class="bg-blue-200"> | ||
<div id="sizer" class="p-4 space-y-4"> | ||
<input | ||
id="synced-input" | ||
type="text" | ||
class="w-full rounded px-2 py-1 ring-2 ring-slate-900/20 focus:outline-none focus:ring-blue-500" | ||
placeholder="Synced input" | ||
value="This input is synced!" | ||
/> | ||
<button | ||
id="colored-button" | ||
data-color="red" | ||
class="px-4 py-2 bg-red-500 text-white font-bold rounded" | ||
> | ||
Click to change the color of this button! | ||
</button> | ||
<p><span class="font-bold">Story time!</span> Fill in the blanks:</p> | ||
|
||
<div class="flex gap-4"> | ||
<input | ||
id="story-village-name-input" | ||
type="text" | ||
class="w-full rounded px-2 py-1 ring-2 ring-slate-900/20 focus:outline-none focus:ring-blue-500" | ||
placeholder="Village name" | ||
value="Whispering Meadows" | ||
/> | ||
<input | ||
id="story-animal-input" | ||
type="text" | ||
class="w-full rounded px-2 py-1 ring-2 ring-slate-900/20 focus:outline-none focus:ring-blue-500" | ||
placeholder="Animal" | ||
value="curious rabbit" | ||
/> | ||
</div> | ||
|
||
<div class="flex gap-4"> | ||
<input | ||
id="story-name-input" | ||
type="text" | ||
class="w-full rounded px-2 py-1 ring-2 ring-slate-900/20 focus:outline-none focus:ring-blue-500" | ||
placeholder="Name" | ||
value="Benny" | ||
/> | ||
<input | ||
id="story-activity-input" | ||
type="text" | ||
class="w-full rounded px-2 py-1 ring-2 ring-slate-900/20 focus:outline-none focus:ring-blue-500" | ||
placeholder="Activity" | ||
value="explore" | ||
/> | ||
</div> | ||
|
||
<div class="flex gap-4"> | ||
<input | ||
id="story-landmark-input" | ||
type="text" | ||
class="w-full rounded px-2 py-1 ring-2 ring-slate-900/20 focus:outline-none focus:ring-blue-500" | ||
placeholder="Landmark" | ||
value="Old Oak Tree" | ||
/> | ||
<input | ||
id="story-object-input" | ||
type="text" | ||
class="w-full rounded px-2 py-1 ring-2 ring-slate-900/20 focus:outline-none focus:ring-blue-500" | ||
placeholder="Object" | ||
value="enchanted compass" | ||
/> | ||
</div> | ||
|
||
<div class="flex gap-4"> | ||
<input | ||
id="story-superpower-input" | ||
type="text" | ||
class="w-full rounded px-2 py-1 ring-2 ring-slate-900/20 focus:outline-none focus:ring-blue-500" | ||
placeholder="Superpower" | ||
value="time travel" | ||
/> | ||
<input | ||
id="story-new-title-input" | ||
type="text" | ||
class="w-full rounded px-2 py-1 ring-2 ring-slate-900/20 focus:outline-none focus:ring-blue-500" | ||
placeholder="New heroic title" | ||
value="Guardian of the Meadows" | ||
/> | ||
</div> | ||
|
||
<button | ||
id="story-button" | ||
class="px-4 py-2 bg-blue-500 text-white font-bold rounded" | ||
> | ||
Tell me a story! | ||
</button> | ||
<p id="story-result" style="display: none"> | ||
The story "<span id="story-title" class="font-bold"></span>" has been | ||
created! | ||
</p> | ||
</div> | ||
<script type="module" src="iframe.js"></script> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
import { | ||
type _RPCPacket, | ||
createRPC, | ||
createRPCRequestHandler, | ||
createTransportFromMessagePort, | ||
type RPCSchema, | ||
} from "../src/index.js"; // "rpc-anywhere" | ||
// import the parent (remote) schema | ||
import { type ParentSchema } from "./parent.js"; | ||
|
||
// grab some elements and prepare some stuff | ||
const syncedInputEl = el<HTMLInputElement>("synced-input"); | ||
const coloredButtonEl = el("colored-button"); | ||
const storyButtonEl = el("story-button"); | ||
const storyResultEl = el("story-result"); | ||
const storyTitleEl = el("story-title"); | ||
const storyVillageNameEl = el<HTMLInputElement>("story-village-name-input"); | ||
const storyAnimalEl = el<HTMLInputElement>("story-animal-input"); | ||
const storyNameEl = el<HTMLInputElement>("story-name-input"); | ||
const storyActivityEl = el<HTMLInputElement>("story-activity-input"); | ||
const storyLandmarkEl = el<HTMLInputElement>("story-landmark-input"); | ||
const storyObjectEl = el<HTMLInputElement>("story-object-input"); | ||
const storySuperpowerEl = el<HTMLInputElement>("story-superpower-input"); | ||
const storyNewTitleEl = el<HTMLInputElement>("story-new-title-input"); | ||
const colors = ["red", "green", "blue", "purple"] as const; | ||
type Color = (typeof colors)[number]; | ||
|
||
// request handler | ||
const requestHandler = createRPCRequestHandler({ | ||
/** | ||
* Get the current color of the button. | ||
*/ | ||
getColor: () => coloredButtonEl.dataset.color as Color, | ||
}); | ||
|
||
// declare the iframe (local) schema | ||
export type IframeSchema = RPCSchema< | ||
{ | ||
messages: { | ||
/** | ||
* Sent when the iframe's RPC is ready. | ||
*/ | ||
ready: void; | ||
/** | ||
* Sent when the iframe's input is updated. | ||
*/ | ||
iframeInputUpdated: string; | ||
}; | ||
}, | ||
// infer request types from the request handler | ||
typeof requestHandler | ||
>; | ||
|
||
function waitForFrameParentLoad() { | ||
if (window.parent.document.readyState === "complete") | ||
return Promise.resolve(); | ||
return new Promise((resolve) => | ||
window.parent.addEventListener("load", resolve), | ||
); | ||
} | ||
|
||
// wait for the parent window to load | ||
waitForFrameParentLoad().then(() => { | ||
console.log("[iframe] The parent has loaded!"); | ||
|
||
// create the iframe's RPC | ||
const rpc = createRPC<IframeSchema, ParentSchema>({ | ||
// provide the transport | ||
transport: createTransportFromMessagePort(window, window.parent, { | ||
// provide a unique ID that matches the parent | ||
transportId: "rpc-anywhere-demo", | ||
}), | ||
// provide the request handler | ||
requestHandler, | ||
// this is for demo purposes - you can ignore it | ||
_debugHooks: { onSend: _debugOnSend, onReceive: _debugOnReceive }, | ||
}); | ||
|
||
// use the proxy as an alias ✨ | ||
const parent = rpc.proxy; | ||
|
||
// send the ready message | ||
parent.send.ready(); | ||
|
||
// synced input | ||
syncedInputEl.addEventListener("input", () => | ||
parent.send.iframeInputUpdated(syncedInputEl.value), | ||
); | ||
rpc.addMessageListener( | ||
"parentInputUpdated", | ||
(value) => (syncedInputEl.value = value), | ||
); | ||
|
||
// story time | ||
storyButtonEl.addEventListener("click", async () => { | ||
const { title } = await parent.request.createStory({ | ||
villageName: storyVillageNameEl.value, | ||
animal: storyAnimalEl.value, | ||
name: storyNameEl.value, | ||
activity: storyActivityEl.value, | ||
landmark: storyLandmarkEl.value, | ||
object: storyObjectEl.value, | ||
superpower: storySuperpowerEl.value, | ||
newTitle: storyNewTitleEl.value, | ||
}); | ||
storyResultEl.style.removeProperty("display"); | ||
storyTitleEl.textContent = title; | ||
}); | ||
}); | ||
|
||
// non-demo stuff - you can ignore this :) | ||
// --------------------------------------- | ||
|
||
const colorToClass = { | ||
red: "bg-red-500", | ||
green: "bg-green-500", | ||
blue: "bg-blue-500", | ||
purple: "bg-purple-500", | ||
}; | ||
function updateButtonColor(color?: Color) { | ||
const currentColor = coloredButtonEl.dataset.color; | ||
const currentClass = colorToClass[currentColor as Color]; | ||
const nextColor = | ||
color ?? | ||
colors[(colors.indexOf(currentColor as Color) + 1) % colors.length]; | ||
const nextClass = colorToClass[nextColor]; | ||
coloredButtonEl.dataset.color = nextColor; | ||
coloredButtonEl.classList.remove(currentClass); | ||
coloredButtonEl.classList.add(nextClass); | ||
} | ||
coloredButtonEl.addEventListener("click", () => updateButtonColor()); | ||
|
||
function el<Element extends HTMLElement>(id: string) { | ||
const element = document.getElementById(id); | ||
if (!element) throw new Error(`Element with id ${id} not found`); | ||
return element as Element; | ||
} | ||
|
||
const iframeLogsEl = window.parent.document.querySelector("#iframe-logs")!; | ||
function _debugOnSend(packet: _RPCPacket) { | ||
console.log("[iframe] sent", packet); | ||
(window.parent as any)._debugAppendMessage("send", iframeLogsEl, packet); | ||
} | ||
function _debugOnReceive(packet: _RPCPacket) { | ||
console.log("[iframe] received", packet); | ||
(window.parent as any)._debugAppendMessage("receive", iframeLogsEl, packet); | ||
} |
Oops, something went wrong.