diff --git a/package-lock.json b/package-lock.json index 934900f4..8ffdba67 100644 --- a/package-lock.json +++ b/package-lock.json @@ -33,7 +33,8 @@ "ts-loader": "^9.5.1", "tsconfig-paths-webpack-plugin": "^4.1.0", "typescript": "^5.5.4", - "web-ext": "^8.2.0" + "web-ext": "^8.2.0", + "wp-types": "^4.66.1" } }, "node_modules/@ampproject/remapping": { @@ -25399,6 +25400,19 @@ "node": ">=0.10.0" } }, + "node_modules/wp-types": { + "version": "4.66.1", + "resolved": "https://registry.npmjs.org/wp-types/-/wp-types-4.66.1.tgz", + "integrity": "sha512-T2sEGcg3MdQ1vojiEMfzO4JpXUPdb+FWgflM6FZln0UTvFwmDBKyNyTik3ODu0nNdAtaSAJzR/HYyqBerKP31g==", + "dev": true, + "license": "MIT", + "dependencies": { + "typescript": ">=4" + }, + "funding": { + "url": "https://github.com/sponsors/johnbillion" + } + }, "node_modules/wrap-ansi": { "version": "7.0.0", "license": "MIT", diff --git a/package.json b/package.json index fd407580..2d535471 100644 --- a/package.json +++ b/package.json @@ -45,7 +45,8 @@ "ts-loader": "^9.5.1", "tsconfig-paths-webpack-plugin": "^4.1.0", "typescript": "^5.5.4", - "web-ext": "^8.2.0" + "web-ext": "^8.2.0", + "wp-types": "^4.66.1" }, "dependencies": { "@wp-playground/client": "^0.9.31", diff --git a/src/api/ApiClient.ts b/src/api/ApiClient.ts new file mode 100644 index 00000000..feec9df8 --- /dev/null +++ b/src/api/ApiClient.ts @@ -0,0 +1,49 @@ +/* eslint-disable camelcase */ + +import { PlaygroundClient } from '@wp-playground/client'; +import { WP_REST_API_Post } from 'wp-types'; + +export interface Post { + id: number; + title: string; +} + +export class ApiClient { + private readonly playgroundClient: PlaygroundClient; + private readonly _siteUrl: string; + + constructor( playgroundClient: PlaygroundClient, siteUrl: string ) { + this.playgroundClient = playgroundClient; + this._siteUrl = siteUrl; + } + + get siteUrl(): string { + return this._siteUrl; + } + + async getPosts(): Promise< Post[] > { + const response = ( await this.get( + '/wp/v2/posts' + ) ) as WP_REST_API_Post[]; + + return response.map( ( post ) => { + return { + id: post.id, + title: post.title.rendered, + }; + } ); + } + + private async get( route: string ): Promise< object > { + const response = await this.playgroundClient.request( { + url: `/index.php?rest_route=${ route }`, + method: 'GET', + } ); + if ( response.httpStatusCode !== 200 ) { + throw Error( response.json.message ); + } + return response.json; + } +} + +/* eslint-enable camelcase */ diff --git a/src/ui/App.tsx b/src/ui/App.tsx index e93d359d..6cf4322c 100644 --- a/src/ui/App.tsx +++ b/src/ui/App.tsx @@ -11,13 +11,15 @@ import { useNavigate, useRouteLoaderData, } from 'react-router-dom'; -import { StrictMode, useEffect } from 'react'; +import { StrictMode, useEffect, useState } from 'react'; import { NewSession } from '@/ui/start/NewSession'; import { ViewSession } from '@/ui/session/ViewSession'; import { Home } from '@/ui/start/Home'; import { getConfig, setConfig } from '@/storage/config'; import { getSession, listSessions, Session } from '@/storage/session'; import { PlaceholderPreview } from '@/ui/preview/PlaceholderPreview'; +import { SessionContext, SessionProvider } from '@/ui/session/SessionProvider'; +import { ApiClient } from '@/api/ApiClient'; export const Screens = { home: () => '/start/home', @@ -75,23 +77,25 @@ function App() { }, [ location ] ); const session = useRouteLoaderData( 'session' ) as Session; + const [ apiClient, setApiClient ] = useState< ApiClient >(); + const sectionContext: SessionContext = { session, apiClient }; const preview = ! session ? ( ) : ( - + ); return ( - <> +
- +
{ preview }
- +
); } diff --git a/src/ui/preview/Playground.tsx b/src/ui/preview/Playground.tsx index 4e7d9c96..5bf50c7b 100644 --- a/src/ui/preview/Playground.tsx +++ b/src/ui/preview/Playground.tsx @@ -4,17 +4,14 @@ import { StartPlaygroundOptions, startPlaygroundWeb, } from '@wp-playground/client'; +import { ApiClient } from '@/api/ApiClient'; const playgroundIframeId = 'playground'; -export interface PlaygroundInfo { - url: string; -} - export function Playground( props: { slug: string; className?: string; - onReady: ( info: PlaygroundInfo ) => void; + onReady: ( apiClient: ApiClient ) => void; } ) { const { slug, className, onReady } = props; @@ -29,12 +26,16 @@ export function Playground( props: { } initPlayground( iframe, slug ) - .then( async ( client: PlaygroundClient ) => { - const info = { - url: await client.absoluteUrl, - }; - console.log( 'Playground communication established!', info ); - onReady( info ); + .then( async ( playgroundClient: PlaygroundClient ) => { + const apiClient = new ApiClient( + playgroundClient, + await playgroundClient.absoluteUrl + ); + console.log( + 'Playground communication established!', + apiClient.siteUrl + ); + onReady( apiClient ); } ) .catch( ( error ) => { throw error; diff --git a/src/ui/preview/Preview.tsx b/src/ui/preview/Preview.tsx index 70cff15b..06fb934b 100644 --- a/src/ui/preview/Preview.tsx +++ b/src/ui/preview/Preview.tsx @@ -1,19 +1,23 @@ import { useState } from 'react'; import { PreviewTabBar } from '@/ui/preview/PreviewTabBar'; -import { Playground, PlaygroundInfo } from '@/ui/preview/Playground'; +import { Playground } from '@/ui/preview/Playground'; +import { useSessionContext } from '@/ui/session/SessionProvider'; +import { ApiClient } from '@/api/ApiClient'; const tabFront = 0; const tabAdmin = 1; const defaultTab = tabFront; -export function Preview( props: { sessionId: string } ) { - const { sessionId } = props; +export function Preview( props: { + onReady: ( apiClient: ApiClient ) => void; +} ) { + const { onReady } = props; const [ currentTab, setCurrentTab ] = useState< number >( defaultTab ); - const [ playgroundInfo, setPlaygroundInfo ] = useState< PlaygroundInfo >(); + const { session, apiClient } = useSessionContext(); const previewAdminUrl = - playgroundInfo?.url && playgroundInfo.url?.length > 0 - ? `${ playgroundInfo.url }/wp-admin/` + apiClient?.siteUrl && apiClient.siteUrl?.length > 0 + ? `${ apiClient.siteUrl }/wp-admin/` : ''; const isPlaygroundLoading = previewAdminUrl === ''; @@ -28,17 +32,10 @@ export function Preview( props: { sessionId: string } ) { /> ); - const previewFront = ( - { - setPlaygroundInfo( info ); - } } - /> - ); + const previewFront = ; const previewAdmin = ( -