From bb669d3abeb25a994e0ccd318fbb1c8acf1c90a3 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Wed, 16 Nov 2022 10:48:21 +0100 Subject: [PATCH] feat: able to query pages with loadProject --- packages/http-client/src/index.d.ts | 8 +++- packages/http-client/src/index.test.ts | 20 +++++++++- packages/http-client/src/index.ts | 55 ++++++++++++++++++++++++-- 3 files changed, 76 insertions(+), 7 deletions(-) diff --git a/packages/http-client/src/index.d.ts b/packages/http-client/src/index.d.ts index 178b0828c3..2d7e6c1b4f 100644 --- a/packages/http-client/src/index.d.ts +++ b/packages/http-client/src/index.d.ts @@ -4,13 +4,17 @@ import type { UserProp, } from "@webstudio-is/react-sdk"; -export type IncludeTypes = "tree" | "props" | "breakpoints"; +export type IncludeTypes = "tree" | "props" | "breakpoints" | "pages"; export type Includes = { [include in IncludeTypes]: T }; - +export type Page = { + id: string; + root: [string, string]; +}; export type Project = { tree: BaseInstance & { errors: string }; props: Array & { errors: string }; breakpoints: Array & { errors: string; }; + pages: Record | null; }; diff --git a/packages/http-client/src/index.test.ts b/packages/http-client/src/index.test.ts index 4e1065e9f9..fdcf40efc9 100644 --- a/packages/http-client/src/index.test.ts +++ b/packages/http-client/src/index.test.ts @@ -1,10 +1,26 @@ import { loadProject } from "./index"; -const existingProjectId = "ab3619d3-831f-46f8-abb6-609558cffd99"; +const existingProjectId = "398d3918-9b00-4a43-8ab6-de4e151ae98a"; const notPublishedProjectId = "7ec397c6-b3d0-4967-9073-9d83623fcf8e"; const apiUrl = "http://localhost:3000"; describe("getProjectDetails", () => { + test("include pages", async () => { + const response = await loadProject({ + apiUrl, + projectId: existingProjectId, + include: { tree: true, props: true, breakpoints: true, pages: true }, + }); + expect(response.pages).toBeTruthy(); + }); + test("does not include pages", async () => { + const response = await loadProject({ + apiUrl, + projectId: notPublishedProjectId, + include: { tree: true, props: true, breakpoints: true, pages: true }, + }); + expect(response.pages).toBeNull(); + }); test("loads existing project", async () => { const response = await loadProject({ apiUrl, @@ -18,7 +34,7 @@ describe("getProjectDetails", () => { projectId: notPublishedProjectId, }); expect(response.tree.errors).toBe( - "Project 7ec397c6-b3d0-4967-9073-9d83623fcf8e needs to be published first" + `Project ${notPublishedProjectId} needs to be published first` ); }); }); diff --git a/packages/http-client/src/index.ts b/packages/http-client/src/index.ts index 6dec39ec30..e88c6dee33 100644 --- a/packages/http-client/src/index.ts +++ b/packages/http-client/src/index.ts @@ -4,7 +4,7 @@ import type { Includes, Project } from "./index.d"; export const loadProject = async ({ apiUrl, projectId, - include = { tree: true, props: true, breakpoints: true }, + include = { tree: true, props: true, breakpoints: true, pages: false }, }: { apiUrl: string; projectId: string; @@ -13,19 +13,68 @@ export const loadProject = async ({ if (apiUrl === undefined) { throw new Error("Webstudio API URL is required."); } - const baseUrl = new URL(`${apiUrl}`); + const urls = []; + let pages: Record | null = {}; + + const baseUrl = new URL(apiUrl); const treeUrl = new URL(`/rest/tree/${projectId}`, baseUrl); const propsUrl = new URL(`/rest/props/${projectId}`, baseUrl); const breakpointsUrl = new URL(`/rest/breakpoints/${projectId}`, baseUrl); + const pagesUrl = new URL(`/rest/pages/${projectId}`, baseUrl); - const [tree, props, breakpoints] = await Promise.all([ + const [tree, props, breakpoints, listOfPages] = await Promise.all([ include.tree && (await fetch(treeUrl)).json(), include.props && (await fetch(propsUrl)).json(), include.breakpoints && (await fetch(breakpointsUrl)).json(), + include.pages && (await fetch(pagesUrl)).json(), ]); + + if (include.pages && listOfPages.pages && listOfPages.pages.length > 0) { + for (const page of listOfPages.pages) { + urls.push({ + url: new URL(`/rest/tree/${projectId}/${page.id}`, baseUrl), + path: page.path, + type: "tree", + }); + urls.push({ + url: new URL(`/rest/props/${projectId}/${page.id}`, baseUrl), + path: page.path, + type: "props", + }); + } + if (urls.length === 0) { + return { + tree, + props, + breakpoints, + pages, + }; + } + + const pagesData = await Promise.all([ + ...urls.map(async (url) => { + const res = await fetch(url.url); + if (res.ok) { + return { path: url.path, type: url.type, data: await res.json() }; + } + }), + ]); + if (Object.keys(pagesData).length > 0) { + for (const page of pagesData) { + if (page && page.path && page.type && page.data) { + pages[page.path] = { + ...(pages[page.path] as Record), + [page.type]: page.data, + breakpoints, + }; + } + } + } + } return { tree, props, breakpoints, + pages: Object.keys(pages).length > 0 ? pages : null, }; };