Skip to content

Commit

Permalink
feat: external object props (#21)
Browse files Browse the repository at this point in the history
* feat: external object props

* chore: cleanup

* chore: update lockfile
  • Loading branch information
agazso authored Sep 9, 2023
1 parent 78fb4c4 commit 2ff3055
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 13 deletions.
37 changes: 34 additions & 3 deletions objects/sandbox-example/src/App.svelte
Original file line number Diff line number Diff line change
@@ -1,9 +1,38 @@
<script lang="ts">
import { makeWakuObjectAdapter, makeWakuObjectContext, startEventListener } from "@waku-objects/adapter"
import { onMount } from "svelte";
import type { DataMessage, WakuObjectArgs } from "@waku-objects/adapter/dist/types";
import { afterUpdate, onMount } from "svelte";
let args: WakuObjectArgs
let message: DataMessage
onMount(() => {
startEventListener()
startEventListener({
onContextChange: async (stateProps, contextProps) => {
const adapter = makeWakuObjectAdapter()
const context = makeWakuObjectContext(adapter, contextProps)
args = {
...context,
...stateProps,
}
},
onDataMessage: async (message_, args_) => {
args = args_
message = message_
}
})
})
afterUpdate(() => {
const { scrollWidth, scrollHeight } = document.body
parent.postMessage(
{
type: 'window-size',
scrollWidth,
scrollHeight,
},
'*',
)
})
async function action() {
Expand All @@ -14,4 +43,6 @@
}
</script>

<div><button on:click={() => action()}>Sandbox example</button></div>
<div>
<button on:click={() => action()}>Sandbox example</button>
</div>
28 changes: 22 additions & 6 deletions packages/adapter/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import pDefer, { DeferredPromise } from "p-defer";
import { DataMessage, JSONSerializable, Token, TokenSchema, TransactionSchema, TransactionStateSchema, WakuObjectAdapter, WakuObjectArgs, WakuObjectContext, WakuObjectState } from './types'
import { DataMessage, JSONSerializable, Token, TokenSchema, TransactionSchema, TransactionStateSchema, WakuObjectAdapter, WakuObjectArgs, WakuObjectContext, WakuObjectContextProps, WakuObjectState } from './types'
import { Contract } from "ethers";

interface AdapterRequestMessage {
Expand Down Expand Up @@ -31,11 +31,13 @@ export interface IframeDataMessage {
type: 'iframe-data-message'
message: DataMessage
state: WakuObjectState
context: WakuObjectContextProps
}

export interface IframeStartMessage {
type: 'iframe-start-message'
export interface IframeContextChange {
type: 'iframe-context-change'
state: WakuObjectState
context: WakuObjectContextProps
}

// Store
Expand Down Expand Up @@ -72,6 +74,10 @@ function isIframeDataMessage(message: any): message is IframeDataMessage {
return typeof message == "object" && message?.type === "iframe-data-message"
}

function isIframeContextChange(message: any): message is IframeContextChange {
return typeof message == "object" && message?.type === 'iframe-context-change'
}

const isAdapterResponseMessage = (message: any): message is AdapterResponseMessage => {
return typeof message == "object" && message?.type === "adapter" && typeof message?.id === 'string';
};
Expand Down Expand Up @@ -166,7 +172,7 @@ export function makeWakuObjectAdapter(): WakuObjectAdapter {
}
}

export function makeWakuObjectContext(adapter: WakuObjectAdapter): WakuObjectContext {
export function makeWakuObjectContext(adapter: WakuObjectAdapter, contextProps?: Partial<WakuObjectContextProps>): WakuObjectContext {
async function send(data: JSONSerializable) {
const response = await adapterFunction('send')(JSON.stringify(data))
if (!response) {
Expand All @@ -189,6 +195,7 @@ export function makeWakuObjectContext(adapter: WakuObjectAdapter): WakuObjectCon

return {
...adapter,
...contextProps,
send,
updateStore,
onViewChange,
Expand All @@ -197,12 +204,12 @@ export function makeWakuObjectContext(adapter: WakuObjectAdapter): WakuObjectCon

interface EventListenerOptions {
onDataMessage: (dataMessage: DataMessage, args: WakuObjectArgs) => Promise<void>
onContextChange: (state: WakuObjectState, context: WakuObjectContextProps) => Promise<void>
}

export function startEventListener(options: Partial<EventListenerOptions>) {
// Start listener
window.addEventListener("message", (event) => {
console.debug('adapter sdk', { event })
// Check if the message came from the parent (chat app)
/*
if (event.origin !== "null" || event.source !== parent.contentWindow) {
Expand All @@ -215,7 +222,7 @@ export function startEventListener(options: Partial<EventListenerOptions>) {
if (isIframeDataMessage(data)) {
const message = data.message as DataMessage
const adapter = makeWakuObjectAdapter()
const context = makeWakuObjectContext(adapter)
const context = makeWakuObjectContext(adapter, data.context)
const args: WakuObjectArgs = {
...context,
...data.state
Expand All @@ -226,6 +233,12 @@ export function startEventListener(options: Partial<EventListenerOptions>) {
return
}

if (isIframeContextChange(data)) {
if (options.onContextChange) {
options.onContextChange(data.state, data.context)
}
}

if (!isAdapterResponseMessage(data)) {
return;
}
Expand All @@ -245,4 +258,7 @@ export function startEventListener(options: Partial<EventListenerOptions>) {
defer.resolve(data.result.value);
});

// send `init` message after object side initialization is complete
// the host application will respond with the updated context
parent.postMessage({ type: 'init' }, '*')
}
13 changes: 9 additions & 4 deletions packages/adapter/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ export interface JSONArray extends Array<JSONValue> {}

export type JSONValue = JSONPrimitive | JSONObject | JSONArray

export type JSONSerializable = JSONValue
export type JSONSerializable = JSONValue

export interface WakuObjectState {
readonly chatId: string
Expand All @@ -83,24 +83,29 @@ export interface WakuObjectState {
type StoreType = JSONSerializable
type DataMessageType = JSONSerializable

export interface WakuObjectContext extends WakuObjectAdapter {
export interface WakuObjectContextProps {
readonly store?: StoreType
readonly view?: string
}

export interface WakuObjectContext extends WakuObjectContextProps, WakuObjectAdapter {
updateStore: (updater: (state?: StoreType) => StoreType) => void

send: (data: DataMessageType) => Promise<void>

readonly view?: string
onViewChange: (view: string) => void
}

export interface WakuObjectArgs extends WakuObjectContext, WakuObjectState {}

export interface WakuObjectDescriptor {
interface WakuObjectMetadata {
readonly objectId: string
readonly name: string
readonly description: string
readonly logo: string
}

export interface WakuObjectDescriptor extends WakuObjectMetadata {
onMessage?: (message: DataMessage<DataMessageType>, args: WakuObjectArgs) => Promise<void>
}

Expand Down
4 changes: 4 additions & 0 deletions pnpm-lock.yaml

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

0 comments on commit 2ff3055

Please sign in to comment.