From 948bdfb5e93370aecb6cfad6b41267d575c6c743 Mon Sep 17 00:00:00 2001 From: Owen Buckley Date: Sun, 24 Sep 2023 11:44:17 -0400 Subject: [PATCH 01/13] add support for SSR page loader with runtime request object --- package.json | 4 +- packages/cli/src/lib/execute-route-module.js | 5 +- packages/cli/src/lib/resource-utils.js | 52 +++++++++ packages/cli/src/lib/ssr-route-worker.js | 4 +- packages/cli/src/lifecycles/bundle.js | 5 +- packages/cli/src/lifecycles/graph.js | 9 +- packages/cli/src/lifecycles/serve.js | 2 +- .../src/plugins/resource/plugin-api-routes.js | 52 +-------- .../plugins/resource/plugin-standard-html.js | 8 +- .../cases/develop.ssr/develop.ssr.spec.js | 104 +++++++++++++++--- .../test/cases/develop.ssr/src/pages/post.js | 26 +++++ .../serve.default.ssr.spec.js | 53 +++++++-- .../cases/serve.default.ssr/src/pages/post.js | 26 +++++ patches/wc-compiler+0.8.0.patch | 40 +++++++ yarn.lock | 98 ++++++++++++++++- 15 files changed, 395 insertions(+), 93 deletions(-) create mode 100644 packages/cli/test/cases/develop.ssr/src/pages/post.js create mode 100644 packages/cli/test/cases/serve.default.ssr/src/pages/post.js create mode 100644 patches/wc-compiler+0.8.0.patch diff --git a/package.json b/package.json index 20bcc8e25..364a05ae0 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,8 @@ "lint:js": "eslint \"*.{js,md}\" \"./packages/**/**/*.{js,md}\" \"./test/*.js\" \"./www/**/**/*.{js,md}\"", "lint:ts": "eslint \"./packages/**/**/*.ts\"", "lint:css": "stylelint \"./www/**/*.js\", \"./www/**/*.css\"", - "lint": "ls-lint && yarn lint:js && yarn lint:ts && yarn lint:css" + "lint": "ls-lint && yarn lint:js && yarn lint:ts && yarn lint:css", + "postinstall": "patch-package" }, "resolutions": { "lit": "^2.1.1" @@ -48,6 +49,7 @@ "jsdom": "^16.5.0", "lerna": "^3.16.4", "mocha": "^9.1.3", + "patch-package": "^8.0.0", "rimraf": "^2.6.3", "stylelint": "^13.8.0", "stylelint-a11y": "^1.2.3", diff --git a/packages/cli/src/lib/execute-route-module.js b/packages/cli/src/lib/execute-route-module.js index 5b36631fe..eb633e084 100644 --- a/packages/cli/src/lib/execute-route-module.js +++ b/packages/cli/src/lib/execute-route-module.js @@ -1,6 +1,6 @@ import { renderToString, renderFromHTML } from 'wc-compiler'; -async function executeRouteModule({ moduleUrl, compilation, page = {}, prerender = false, htmlContents = null, scripts = [] }) { +async function executeRouteModule({ moduleUrl, compilation, page = {}, prerender = false, htmlContents = null, scripts = [], request }) { const data = { template: null, body: null, @@ -18,7 +18,8 @@ async function executeRouteModule({ moduleUrl, compilation, page = {}, prerender const { getTemplate = null, getBody = null, getFrontmatter = null } = module; if (module.default) { - const { html } = await renderToString(new URL(moduleUrl), false); + const props = module.loader ? await module.loader(request, compilation) : {}; + const { html } = await renderToString(new URL(moduleUrl), false, props); data.body = html; } else { diff --git a/packages/cli/src/lib/resource-utils.js b/packages/cli/src/lib/resource-utils.js index 410c13d60..a3d71e579 100644 --- a/packages/cli/src/lib/resource-utils.js +++ b/packages/cli/src/lib/resource-utils.js @@ -208,11 +208,63 @@ function transformKoaRequestIntoStandardRequest(url, request) { }); } +// https://stackoverflow.com/questions/57447685/how-can-i-convert-a-request-object-into-a-stringifiable-object-in-javascript +async function requestAsObject (_request) { + if (!_request instanceof Request) { + throw Object.assign( + new Error(), + { name: 'TypeError', message: 'Argument must be a Request object' } + ); + } + + const request = _request.clone(); + const contentType = request.headers.get('content-type') || ''; + let headers = Object.fromEntries(request.headers); + let format; + + function stringifiableObject (obj) { + const filtered = {}; + for (const key in obj) { + if (['boolean', 'number', 'string'].includes(typeof obj[key]) || obj[key] === null) { + filtered[key] = obj[key]; + } + } + return filtered; + } + + if (contentType.includes('application/x-www-form-urlencoded')) { + const formData = await request.formData(); + const params = {}; + + for (const entry of formData.entries()) { + params[entry[0]] = entry[1]; + } + + // when using FormData, let Request set the correct headers + // or else it will come out as multipart/form-data + // for serialization between route workers, leave a special marker for Greenwood + // https://stackoverflow.com/a/43521052/417806 + headers['content-type'] = 'x-greenwood/www-form-urlencoded'; + format = JSON.stringify(params); + } else if (contentType.includes('application/json')) { + format = JSON.stringify(await request.json()); + } else { + format = await request.text(); + } + + return { + ...stringifiableObject(request), + body: format, + headers + }; +} + export { checkResourceExists, mergeResponse, modelResource, normalizePathnameForWindows, + requestAsObject, resolveForRelativeUrl, trackResourcesForRoute, transformKoaRequestIntoStandardRequest diff --git a/packages/cli/src/lib/ssr-route-worker.js b/packages/cli/src/lib/ssr-route-worker.js index 12eb71d88..239eb49a3 100644 --- a/packages/cli/src/lib/ssr-route-worker.js +++ b/packages/cli/src/lib/ssr-route-worker.js @@ -1,9 +1,9 @@ // https://github.com/nodejs/modules/issues/307#issuecomment-858729422 import { parentPort } from 'worker_threads'; -async function executeModule({ executeModuleUrl, moduleUrl, compilation, page, prerender = false, htmlContents = null, scripts = '[]' }) { +async function executeModule({ executeModuleUrl, moduleUrl, compilation, page, prerender = false, htmlContents = null, scripts = '[]', request }) { const { executeRouteModule } = await import(executeModuleUrl); - const data = await executeRouteModule({ moduleUrl, compilation: JSON.parse(compilation), page: JSON.parse(page), prerender, htmlContents, scripts: JSON.parse(scripts) }); + const data = await executeRouteModule({ moduleUrl, compilation: JSON.parse(compilation), page: JSON.parse(page), prerender, htmlContents, scripts: JSON.parse(scripts), request }); parentPort.postMessage(data); } diff --git a/packages/cli/src/lifecycles/bundle.js b/packages/cli/src/lifecycles/bundle.js index e931847f6..bea890be6 100644 --- a/packages/cli/src/lifecycles/bundle.js +++ b/packages/cli/src/lifecycles/bundle.js @@ -193,9 +193,10 @@ async function bundleSsrPages(compilation) { const { filename, imports, route, template, title } = page; const entryFileUrl = new URL(`./_${filename}`, scratchDir); const moduleUrl = new URL(`./${filename}`, pagesDir); + const request = new Request(moduleUrl); // TODO not really sure how to best no-op this? // TODO getTemplate has to be static (for now?) // https://github.com/ProjectEvergreen/greenwood/issues/955 - const data = await executeRouteModule({ moduleUrl, compilation, page, prerender: false, htmlContents: null, scripts: [] }); + const data = await executeRouteModule({ moduleUrl, compilation, page, prerender: false, htmlContents: null, scripts: [], request }); let staticHtml = ''; staticHtml = data.template ? data.template : await getPageTemplate(staticHtml, compilation.context, template, []); @@ -212,7 +213,7 @@ async function bundleSsrPages(compilation) { const compilation = JSON.parse('${JSON.stringify(compilation)}'); const page = JSON.parse('${JSON.stringify(page)}'); const moduleUrl = '___GWD_ENTRY_FILE_URL=${filename}___'; - const data = await executeRouteModule({ moduleUrl, compilation, page }); + const data = await executeRouteModule({ moduleUrl, compilation, page, request }); let staticHtml = \`${staticHtml}\`; if (data.body) { diff --git a/packages/cli/src/lifecycles/graph.js b/packages/cli/src/lifecycles/graph.js index 486adb6d1..0a1df92b6 100644 --- a/packages/cli/src/lifecycles/graph.js +++ b/packages/cli/src/lifecycles/graph.js @@ -1,7 +1,7 @@ /* eslint-disable complexity, max-depth */ import fs from 'fs/promises'; import fm from 'front-matter'; -import { checkResourceExists } from '../lib/resource-utils.js'; +import { checkResourceExists, requestAsObject } from '../lib/resource-utils.js'; import toc from 'markdown-toc'; import { Worker } from 'worker_threads'; @@ -121,8 +121,10 @@ const generateGraph = async (compilation) => { filePath = route; - await new Promise((resolve, reject) => { + await new Promise(async (resolve, reject) => { const worker = new Worker(new URL('../lib/ssr-route-worker.js', import.meta.url)); + // TOOD "faux" new Request here, a better way? + const request = await requestAsObject(new Request(filenameUrl)); worker.on('message', async (result) => { if (result.frontmatter) { @@ -151,7 +153,8 @@ const generateGraph = async (compilation) => { .map((idPart) => { return `${idPart.charAt(0).toUpperCase()}${idPart.substring(1)}`; }).join(' ') - }) + }), + request }); }); diff --git a/packages/cli/src/lifecycles/serve.js b/packages/cli/src/lifecycles/serve.js index da386eaaa..f634c340c 100644 --- a/packages/cli/src/lifecycles/serve.js +++ b/packages/cli/src/lifecycles/serve.js @@ -294,8 +294,8 @@ async function getHybridServer(compilation) { const request = transformKoaRequestIntoStandardRequest(url, ctx.request); if (!config.prerender && matchingRoute.isSSR && !matchingRoute.data.static) { + console.log('MATCHING ROUTE -> ', matchingRoute.filename); const { handler } = await import(new URL(`./__${matchingRoute.filename}`, outputDir)); - // TODO passing compilation this way too hacky? const response = await handler(request, compilation); ctx.body = Readable.from(response.body); diff --git a/packages/cli/src/plugins/resource/plugin-api-routes.js b/packages/cli/src/plugins/resource/plugin-api-routes.js index dcb023eb0..6228f3e97 100644 --- a/packages/cli/src/plugins/resource/plugin-api-routes.js +++ b/packages/cli/src/plugins/resource/plugin-api-routes.js @@ -4,59 +4,9 @@ * */ import { ResourceInterface } from '../../lib/resource-interface.js'; +import { requestAsObject } from '../../lib/resource-utils.js'; import { Worker } from 'worker_threads'; -// https://stackoverflow.com/questions/57447685/how-can-i-convert-a-request-object-into-a-stringifiable-object-in-javascript -async function requestAsObject (_request) { - if (!_request instanceof Request) { - throw Object.assign( - new Error(), - { name: 'TypeError', message: 'Argument must be a Request object' } - ); - } - - const request = _request.clone(); - const contentType = request.headers.get('content-type') || ''; - let headers = Object.fromEntries(request.headers); - let format; - - function stringifiableObject (obj) { - const filtered = {}; - for (const key in obj) { - if (['boolean', 'number', 'string'].includes(typeof obj[key]) || obj[key] === null) { - filtered[key] = obj[key]; - } - } - return filtered; - } - - if (contentType.includes('application/x-www-form-urlencoded')) { - const formData = await request.formData(); - const params = {}; - - for (const entry of formData.entries()) { - params[entry[0]] = entry[1]; - } - - // when using FormData, let Request set the correct headers - // or else it will come out as multipart/form-data - // for serialization between route workers, leave a special marker for Greenwood - // https://stackoverflow.com/a/43521052/417806 - headers['content-type'] = 'x-greenwood/www-form-urlencoded'; - format = JSON.stringify(params); - } else if (contentType.includes('application/json')) { - format = JSON.stringify(await request.json()); - } else { - format = await request.text(); - } - - return { - ...stringifiableObject(request), - body: format, - headers - }; -} - class ApiRoutesResource extends ResourceInterface { constructor(compilation, options) { super(compilation, options); diff --git a/packages/cli/src/plugins/resource/plugin-standard-html.js b/packages/cli/src/plugins/resource/plugin-standard-html.js index 4b91d69bc..933893d62 100644 --- a/packages/cli/src/plugins/resource/plugin-standard-html.js +++ b/packages/cli/src/plugins/resource/plugin-standard-html.js @@ -14,6 +14,7 @@ import remarkParse from 'remark-parse'; import remarkRehype from 'remark-rehype'; import { ResourceInterface } from '../../lib/resource-interface.js'; import { getUserScripts, getPageTemplate, getAppTemplate } from '../../lib/templating-utils.js'; +import { requestAsObject } from '../../lib/resource-utils.js'; import unified from 'unified'; import { Worker } from 'worker_threads'; @@ -33,7 +34,7 @@ class StandardHtmlResource extends ResourceInterface { return protocol.startsWith('http') && (hasMatchingPageRoute || isSPA); } - async serve(url) { + async serve(url, request) { const { config, context } = this.compilation; const { pagesDir, userWorkspace } = context; const { interpolateFrontmatter } = config; @@ -107,7 +108,7 @@ class StandardHtmlResource extends ResourceInterface { const routeModuleLocationUrl = new URL(`./${matchingRoute.filename}`, pagesDir); const routeWorkerUrl = this.compilation.config.plugins.find(plugin => plugin.type === 'renderer').provider().executeModuleUrl; - await new Promise((resolve, reject) => { + await new Promise(async (resolve, reject) => { const worker = new Worker(new URL('../../lib/ssr-route-worker.js', import.meta.url)); worker.on('message', (result) => { @@ -146,7 +147,8 @@ class StandardHtmlResource extends ResourceInterface { executeModuleUrl: routeWorkerUrl.href, moduleUrl: routeModuleLocationUrl.href, compilation: JSON.stringify(this.compilation), - page: JSON.stringify(matchingRoute) + page: JSON.stringify(matchingRoute), + request: await requestAsObject(request) }); }); } diff --git a/packages/cli/test/cases/develop.ssr/develop.ssr.spec.js b/packages/cli/test/cases/develop.ssr/develop.ssr.spec.js index 830079fdf..d0fac0374 100644 --- a/packages/cli/test/cases/develop.ssr/develop.ssr.spec.js +++ b/packages/cli/test/cases/develop.ssr/develop.ssr.spec.js @@ -17,6 +17,7 @@ * footer.js * pages/ * artists.js + * post.js * templates/ * app.html */ @@ -134,31 +135,30 @@ describe('Develop Greenwood With: ', function() { }); }); - let response = {}; - let dom; - let artistsPageGraphData; + describe('Develop command with HTML route response using getTemplate, getBody, getFrontmatter', function() { + let response = {}; + let dom; + let artistsPageGraphData; - before(async function() { - const graph = JSON.parse(await fs.promises.readFile(path.join(outputPath, '.greenwood/graph.json'), 'utf-8')); + before(async function() { + const graph = JSON.parse(await fs.promises.readFile(path.join(outputPath, '.greenwood/graph.json'), 'utf-8')); - artistsPageGraphData = graph.filter(page => page.route === '/artists/')[0]; + artistsPageGraphData = graph.filter(page => page.route === '/artists/')[0]; - return new Promise((resolve, reject) => { - request.get(`${hostname}/artists/`, (err, res, body) => { - if (err) { - reject(); - } + return new Promise((resolve, reject) => { + request.get(`${hostname}/artists/`, (err, res, body) => { + if (err) { + reject(); + } - response = res; - response.body = body; - dom = new JSDOM(body); + response = res; + response.body = body; + dom = new JSDOM(body); - resolve(); + resolve(); + }); }); }); - }); - - describe('Serve command with HTML route response', function() { it('should return a 200 status', function(done) { expect(response.statusCode).to.equal(200); @@ -236,6 +236,74 @@ describe('Develop Greenwood With: ', function() { expect(counterScript.length).to.equal(1); }); }); + + describe('Develop command with HTML route response using default export and request time data', function() { + const postId = 1; + let response = {}; + let dom = {}; + + before(async function() { + return new Promise((resolve, reject) => { + request.get(`${hostname}/post/?id=${postId}`, (err, res, body) => { + if (err) { + reject(); + } + + response = res; + response.body = body; + dom = new JSDOM(body); + + resolve(); + }); + }); + }); + + it('should return a 200 status', function(done) { + expect(response.statusCode).to.equal(200); + done(); + }); + + it('should return the correct content type', function(done) { + expect(response.headers['content-type']).to.equal('text/html'); + done(); + }); + + it('should return a response body', function(done) { + expect(response.body).to.not.be.undefined; + done(); + }); + + it('should be valid HTML from JSDOM', function(done) { + expect(dom).to.not.be.undefined; + done(); + }); + + it('should be valid HTML from JSDOM', function(done) { + expect(dom).to.not.be.undefined; + done(); + }); + + it('should have the expected postId as an

tag in the body', function() { + const heading = dom.window.document.querySelectorAll('body > h1'); + + expect(heading.length).to.equal(1); + expect(heading[0].textContent).to.equal(`Fetched Post ID: ${postId}`); + }); + + it('should have the expected title as an

tag in the body', function() { + const heading = dom.window.document.querySelectorAll('body > h2'); + + expect(heading.length).to.equal(1); + expect(heading[0].textContent).to.not.be.undefined; + }); + + it('should have the expected body as a

tag in the body', function() { + const paragraph = dom.window.document.querySelectorAll('body > p'); + + expect(paragraph.length).to.equal(1); + expect(paragraph[0].textContent).to.not.be.undefined; + }); + }); }); after(function() { diff --git a/packages/cli/test/cases/develop.ssr/src/pages/post.js b/packages/cli/test/cases/develop.ssr/src/pages/post.js new file mode 100644 index 000000000..86af3b3f4 --- /dev/null +++ b/packages/cli/test/cases/develop.ssr/src/pages/post.js @@ -0,0 +1,26 @@ +export default class PostPage extends HTMLElement { + constructor({ post = {} }) { + super(); + this.post = post; + } + + async connectedCallback() { + const { id, title, body } = this.post; + + this.innerHTML = ` +

Fetched Post ID: ${id}

+

${title}

+

${body}

+ `; + } +} + +export async function loader(request) { + const params = new URLSearchParams(request.url.slice(request.url.indexOf('?'))); + const postId = params.get('id'); + const post = await fetch(`https://jsonplaceholder.typicode.com/posts/${postId}`).then(resp => resp.json()); + + return { + post + }; +} \ No newline at end of file diff --git a/packages/cli/test/cases/serve.default.ssr/serve.default.ssr.spec.js b/packages/cli/test/cases/serve.default.ssr/serve.default.ssr.spec.js index bf60ae24c..27e0b265f 100644 --- a/packages/cli/test/cases/serve.default.ssr/serve.default.ssr.spec.js +++ b/packages/cli/test/cases/serve.default.ssr/serve.default.ssr.spec.js @@ -286,14 +286,6 @@ describe('Serve Greenwood With: ', function() { expect(cards.length).to.be.greaterThan(0); }); - xit('should have a bundled + + + + + + + \ No newline at end of file From b4472d057161bbaef6da7509b1f6ab6b9f8e900a Mon Sep 17 00:00:00 2001 From: Owen Buckley Date: Sat, 14 Oct 2023 21:12:20 -0400 Subject: [PATCH 09/13] upgrade website for breaking changes --- www/components/header/header.js | 4 ++-- www/components/shelf/shelf.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/www/components/header/header.js b/www/components/header/header.js index 345b9e4d5..5a708a06e 100644 --- a/www/components/header/header.js +++ b/www/components/header/header.js @@ -1,6 +1,6 @@ import { css, html, LitElement, unsafeCSS } from 'lit'; -import client from '@greenwood/plugin-graphql/core/client'; -import MenuQuery from '@greenwood/plugin-graphql/queries/menu'; +import client from '@greenwood/plugin-graphql/src/core/client.js'; +import MenuQuery from '@greenwood/plugin-graphql/src/queries/menu.gql'; import '@evergreen-wc/eve-container'; import headerCss from './header.css?type=css'; import '../social-icons/social-icons.js'; diff --git a/www/components/shelf/shelf.js b/www/components/shelf/shelf.js index 90cbd0b8b..1b555977a 100644 --- a/www/components/shelf/shelf.js +++ b/www/components/shelf/shelf.js @@ -1,6 +1,6 @@ import { css, html, LitElement, unsafeCSS } from 'lit'; -import client from '@greenwood/plugin-graphql/core/client'; -import MenuQuery from '@greenwood/plugin-graphql/queries/menu'; +import client from '@greenwood/plugin-graphql/src/core/client.js'; +import MenuQuery from '@greenwood/plugin-graphql/src/queries/menu.gql'; import shelfCss from './shelf.css?type=css'; import chevronRt from '../icons/chevron-right.js'; import chevronDwn from '../icons/chevron-down.js'; From 6fce8fc1f734699ed237beabe1c457577dab1770 Mon Sep 17 00:00:00 2001 From: Owen Buckley Date: Sat, 14 Oct 2023 21:28:25 -0400 Subject: [PATCH 10/13] update website documentation and graphql plugin package README --- packages/plugin-graphql/README.md | 30 +++++++++++------------------- www/pages/docs/data.md | 16 ++++++++-------- www/pages/docs/menus.md | 4 ++-- 3 files changed, 21 insertions(+), 29 deletions(-) diff --git a/packages/plugin-graphql/README.md b/packages/plugin-graphql/README.md index dc4896c50..88351039c 100644 --- a/packages/plugin-graphql/README.md +++ b/packages/plugin-graphql/README.md @@ -1,23 +1,15 @@ # @greenwood/plugin-graphql ## Overview -A plugin for Greenwood to support using [GraphQL](https://graphql.org/) to query Greenwood's content graph. It runs [**apollo-server**](https://www.apollographql.com/docs/apollo-server/) on the backend and provides an [**@apollo/client** _"like"_](https://www.apollographql.com/docs/react/api/core/ApolloClient/#ApolloClient.readQuery) interface for the frontend that you can use. +A plugin for Greenwood to support using [GraphQL](https://graphql.org/) to query Greenwood's [content graph](https://www.greenwoodjs.io/docs/data/) with our optoinal [pre-made queries](https://www.greenwoodjs.io/docs/menus/). It runs [**apollo-server**](https://www.apollographql.com/docs/apollo-server/) on the backend at build time and provides a **"read-only"** [**@apollo/client** _"like"_](https://www.apollographql.com/docs/react/api/core/ApolloClient/#ApolloClient.readQuery) interface for the frontend that you can use. > This package assumes you already have `@greenwood/cli` installed. ## Caveats -As of now, this plugin can only be used in conjunction with our [Puppeteer rendering plugin](https://github.com/ProjectEvergreen/greenwood/tree/master/packages/plugin-renderer-puppeteer). Please make sure you have it installed first to get the benefits of this plugin. - -```bash -# npm -npm install @greenwood/plugin-renderer-puppeteer --save-dev - -# yarn -yarn add @greenwood/plugin-renderer-puppeteer --dev -``` - -> _We are working on re-evaluating and improving our [data loading](https://github.com/ProjectEvergreen/greenwood/issues/952) and [rendering strategies](https://github.com/ProjectEvergreen/greenwood/issues/951) as part of our [1.0 release](https://github.com/ProjectEvergreen/greenwood/milestone/3)._ +As of now, this plugin requires some form of [prerendering](https://www.greenwoodjs.io/docs/server-rendering/#render-vs-prerender) either through: +1. Enabling [custom imports](https://www.greenwoodjs.io/docs/server-rendering/#custom-imports) +1. Installing the [Puppeteer renderer plugin](https://github.com/ProjectEvergreen/greenwood/tree/master/packages/plugin-renderer-puppeteer). ## Installation @@ -32,15 +24,15 @@ yarn add @greenwood/plugin-graphql --dev ``` ## Usage -Add this plugin and the Puppeteer plugins to your _greenwood.config.js_. +Add this plugin to your _greenwood.config.js_ and configure with either `prerender: true` _or_ by adding the `greenwoodPluginRendererPuppeteer` plugin. ```javascript import { greenwoodPluginGraphQL } from '@greenwood/plugin-graphql'; -import { greenwoodPluginRendererPuppeteer } from '@greenwood/plugin-renderer-puppeteer'; +import { greenwoodPluginRendererPuppeteer } from '@greenwood/plugin-renderer-puppeteer'; // if using puppeteer export default { // ... - + prerender: true, // if using custom imports plugins: [ greenwoodPluginGraphQL(), greenwoodPluginRendererPuppeteer() @@ -52,8 +44,8 @@ export default { This will then allow you to use GraphQL to query your content from your client side. At build time, it will generate JSON files so that the data is still accessible statically. ```js -import client from '@greenwood/plugin-graphql/core/client'; -import MenuQuery from '@greenwood/plugin-graphql/queries/menu'; +import client from '@greenwood/plugin-graphql/src/core/client.js'; +import MenuQuery from '@greenwood/plugin-graphql/src/queries/menu.gql'; class HeaderComponent extends HTMLElement { constructor() { @@ -82,7 +74,7 @@ class HeaderComponent extends HTMLElement { ${menuItem.label} `; - }).join(); + }).join(''); return `
@@ -174,7 +166,7 @@ query($name: String!) { And then you can use it in your code as such: ```js -import client from '@greenwood/plugin-graphql/core/client'; +import client from '@greenwood/plugin-graphql/src/core/client.js'; import GalleryQuery from '../relative/path/to/data/queries/gallery.gql'; client.query({ diff --git a/www/pages/docs/data.md b/www/pages/docs/data.md index d7ca68db7..d9423484a 100644 --- a/www/pages/docs/data.md +++ b/www/pages/docs/data.md @@ -101,8 +101,8 @@ query { ###### Usage `import` the query in your component ```javascript -import client from '@greenwood/plugin-graphql/core/client'; -import GraphQuery from '@greenwood/plugin-graphql/queries/menu'; +import client from '@greenwood/plugin-graphql/src/core/client.js'; +import GraphQuery from '@greenwood/plugin-graphql/src/queries/menu.gql'; . . @@ -180,8 +180,8 @@ query { ###### Usage `import` the query in your component ```javascript -import client from '@greenwood/plugin-graphql/core/client'; -import ChildrenQuery from '@greenwood/plugin-graphql/queries/menu'; +import client from '@greenwood/plugin-graphql/src/core/client.js'; +import ChildrenQuery from '@greenwood/plugin-graphql/src/queries/menu.gql'; . . @@ -257,8 +257,8 @@ query { ###### Usage `import` the query in your component ```javascript -import client from '@greenwood/plugin-graphql/core/client'; -import ConfigQuery from '@greenwood/plugin-graphql/queries/menu'; +import client from '@greenwood/plugin-graphql/src/core/client.js'; +import ConfigQuery from '@greenwood/plugin-graphql/src/queries/menu.gql'; . . . @@ -323,8 +323,8 @@ Now of course comes the fun part, actually seeing it all come together. Here is ```javascript import { LitElement, html } from 'lit'; -import client from '@greenwood/plugin-graphql/core/client'; -import MenuQuery from '@greenwood/plugin-graphql/queries/menu'; +import client from '@greenwood/plugin-graphql/src/core/client.js'; +import MenuQuery from '@greenwood/plugin-graphql/src/queries/menu.gql'; class HeaderComponent extends LitElement { diff --git a/www/pages/docs/menus.md b/www/pages/docs/menus.md index 2358c23f8..bd473da0e 100644 --- a/www/pages/docs/menus.md +++ b/www/pages/docs/menus.md @@ -80,8 +80,8 @@ Now in order to use our navigation menu within a component we need to query it v ```js // navigation.js import { LitElement, html } from 'lit'; -import client from '@greenwood/plugin-graphql/core/client'; -import MenuQuery from '@greenwood/plugin-graphql/queries/menu'; +import client from '@greenwood/plugin-graphql/src/core/client.js'; +import MenuQuery from '@greenwood/plugin-graphql/src/queries/menu.gql'; class HeaderComponent extends LitElement { From a51abeeb42d2749e1395031a559898eb614d2607 Mon Sep 17 00:00:00 2001 From: Owen Buckley Date: Mon, 16 Oct 2023 21:12:00 -0400 Subject: [PATCH 11/13] add test cases for adapter plugins and SSR constructor props --- .../cases/build.default/build.default.spec.js | 52 +++++++++++++++++-- .../cases/build.default/src/pages/post.js | 20 +++++++ .../cases/build.default/build.default.spec.js | 49 ++++++++++++++++- .../cases/build.default/src/pages/post.js | 20 +++++++ 4 files changed, 137 insertions(+), 4 deletions(-) create mode 100644 packages/plugin-adapter-netlify/test/cases/build.default/src/pages/post.js create mode 100644 packages/plugin-adapter-vercel/test/cases/build.default/src/pages/post.js diff --git a/packages/plugin-adapter-netlify/test/cases/build.default/build.default.spec.js b/packages/plugin-adapter-netlify/test/cases/build.default/build.default.spec.js index e93209128..a2ca84736 100644 --- a/packages/plugin-adapter-netlify/test/cases/build.default/build.default.spec.js +++ b/packages/plugin-adapter-netlify/test/cases/build.default/build.default.spec.js @@ -30,6 +30,7 @@ * card.js * pages/ * artists.js + * post.js * users.js * services/ * artists.js @@ -77,8 +78,8 @@ describe('Build Greenwood With: ', function() { redirectsFile = await glob.promise(path.join(outputPath, 'public/_redirects')); }); - it('should output the expected number of serverless function zip files', function() { - expect(zipFiles.length).to.be.equal(7); + it('', function() { + expect(zipFiles.length).to.be.equal(8); }); it('should output the expected number of serverless function API zip files', function() { @@ -86,7 +87,7 @@ describe('Build Greenwood With: ', function() { }); it('should output the expected number of serverless function SSR page zip files', function() { - expect(zipFiles.filter(file => !path.basename(file).startsWith('api-')).length).to.be.equal(2); + expect(zipFiles.filter(file => !path.basename(file).startsWith('api-')).length).to.be.equal(3); }); it('should output a _redirects file', function() { @@ -303,6 +304,50 @@ describe('Build Greenwood With: ', function() { }); }); + describe('Post SSR Page adapter', function() { + let pageFunctions; + + before(async function() { + pageFunctions = (await glob.promise(path.join(normalizePathnameForWindows(netlifyFunctionsOutputUrl), '*.zip'))) + .filter(zipFile => path.basename(zipFile).startsWith('post')); + }); + + it('should output one SSR page as a serverless function zip file', function() { + expect(pageFunctions.length).to.be.equal(1); + }); + + it('should return the expected response when the serverless adapter entry point handler is invoked', async function() { + const name = path.basename(pageFunctions[0]).replace('.zip', ''); + const postId = 1; + + await extract(pageFunctions[0], { + dir: path.join(normalizePathnameForWindows(netlifyFunctionsOutputUrl), name) + }); + const { handler } = await import(new URL(`./${name}/${name}.js`, netlifyFunctionsOutputUrl)); + const response = await handler({ + rawUrl: `http://localhost:8080/post/?id=${postId}`, + httpMethod: 'GET' + }, {}); + + const { statusCode, body, headers } = response; + const dom = new JSDOM(body); + const headingOne = dom.window.document.querySelectorAll('body > h1'); + const headingTwo = dom.window.document.querySelectorAll('body > h2'); + const paragraph = dom.window.document.querySelectorAll('body > p'); + + expect(statusCode).to.be.equal(200); + expect(headers.get('content-type')).to.be.equal('text/html'); + + expect(headingOne.length).to.be.equal(1); + expect(headingTwo.length).to.be.equal(1); + expect(paragraph.length).to.be.equal(1); + + expect(headingOne[0].textContent).to.be.equal(`Fetched Post ID: ${postId}`); + expect(headingTwo[0].textContent).to.not.be.undefined; + expect(paragraph[0].textContent).to.not.be.undefined; + }); + }); + describe('_redirects file contents', function() { let redirectsFileContents; @@ -313,6 +358,7 @@ describe('Build Greenwood With: ', function() { it('should return the expected response when the serverless adapter entry point handler is invoked', async function() { expect(redirectsFileContents).to.be.equal( `/artists/ /.netlify/functions/artists 200 +/post/ /.netlify/functions/post 200 /users/ /.netlify/functions/users 200 /api/* /.netlify/functions/api-:splat 200` ); diff --git a/packages/plugin-adapter-netlify/test/cases/build.default/src/pages/post.js b/packages/plugin-adapter-netlify/test/cases/build.default/src/pages/post.js new file mode 100644 index 000000000..a5d7d10d6 --- /dev/null +++ b/packages/plugin-adapter-netlify/test/cases/build.default/src/pages/post.js @@ -0,0 +1,20 @@ +export default class PostPage extends HTMLElement { + constructor(request) { + super(); + + const params = new URLSearchParams(request.url.slice(request.url.indexOf('?'))); + this.postId = params.get('id'); + } + + async connectedCallback() { + const { postId } = this; + const post = await fetch(`https://jsonplaceholder.typicode.com/posts/${postId}`).then(resp => resp.json()); + const { id, title, body } = post; + + this.innerHTML = ` +

Fetched Post ID: ${id}

+

${title}

+

${body}

+ `; + } +} \ No newline at end of file diff --git a/packages/plugin-adapter-vercel/test/cases/build.default/build.default.spec.js b/packages/plugin-adapter-vercel/test/cases/build.default/build.default.spec.js index 014522efa..e2ead1293 100644 --- a/packages/plugin-adapter-vercel/test/cases/build.default/build.default.spec.js +++ b/packages/plugin-adapter-vercel/test/cases/build.default/build.default.spec.js @@ -30,6 +30,7 @@ * card.js * pages/ * artists.js + * post.js * users.js * services/ * artists.js @@ -79,7 +80,7 @@ describe('Build Greenwood With: ', function() { }); it('should output the expected number of serverless function output folders', function() { - expect(functionFolders.length).to.be.equal(7); + expect(functionFolders.length).to.be.equal(8); }); it('should output the expected configuration file for the build output', function() { @@ -333,6 +334,52 @@ describe('Build Greenwood With: ', function() { expect(headers.get('content-type')).to.be.equal('text/html'); }); }); + + describe('Post SSR Page adapter', function() { + const postId = 1; + + it('should return the expected response when the serverless adapter entry point handler is invoked', async function() { + const handler = (await import(new URL('./post.func/index.js', vercelFunctionsOutputUrl))).default; + const response = { + headers: new Headers() + }; + + await handler({ + url: `http://localhost:8080/post/?id=${postId}`, + headers: { + host: 'http://localhost:8080' + }, + method: 'GET' + }, { + status: function(code) { + response.status = code; + }, + send: function(body) { + response.body = body; + }, + setHeader: function(key, value) { + response.headers.set(key, value); + } + }); + + const { status, body, headers } = response; + const dom = new JSDOM(body); + const headingOne = dom.window.document.querySelectorAll('body > h1'); + const headingTwo = dom.window.document.querySelectorAll('body > h2'); + const paragraph = dom.window.document.querySelectorAll('body > p'); + + expect(status).to.be.equal(200); + expect(headers.get('content-type')).to.be.equal('text/html'); + + expect(headingOne.length).to.be.equal(1); + expect(headingTwo.length).to.be.equal(1); + expect(paragraph.length).to.be.equal(1); + + expect(headingOne[0].textContent).to.be.equal(`Fetched Post ID: ${postId}`); + expect(headingTwo[0].textContent).to.not.be.undefined; + expect(paragraph[0].textContent).to.not.be.undefined; + }); + }); }); after(function() { diff --git a/packages/plugin-adapter-vercel/test/cases/build.default/src/pages/post.js b/packages/plugin-adapter-vercel/test/cases/build.default/src/pages/post.js new file mode 100644 index 000000000..a5d7d10d6 --- /dev/null +++ b/packages/plugin-adapter-vercel/test/cases/build.default/src/pages/post.js @@ -0,0 +1,20 @@ +export default class PostPage extends HTMLElement { + constructor(request) { + super(); + + const params = new URLSearchParams(request.url.slice(request.url.indexOf('?'))); + this.postId = params.get('id'); + } + + async connectedCallback() { + const { postId } = this; + const post = await fetch(`https://jsonplaceholder.typicode.com/posts/${postId}`).then(resp => resp.json()); + const { id, title, body } = post; + + this.innerHTML = ` +

Fetched Post ID: ${id}

+

${title}

+

${body}

+ `; + } +} \ No newline at end of file From 806e9e9d7fd2fd9ca610fe8a5078e4b556a95c41 Mon Sep 17 00:00:00 2001 From: Owen Buckley Date: Fri, 27 Oct 2023 21:07:05 -0400 Subject: [PATCH 12/13] upgrade wcc to 0.9.0 --- package.json | 4 +- packages/cli/package.json | 2 +- packages/plugin-import-jsx/package.json | 2 +- patches/wc-compiler+0.8.0.patch | 40 --------- yarn.lock | 106 ++---------------------- 5 files changed, 9 insertions(+), 145 deletions(-) delete mode 100644 patches/wc-compiler+0.8.0.patch diff --git a/package.json b/package.json index 364a05ae0..20bcc8e25 100644 --- a/package.json +++ b/package.json @@ -27,8 +27,7 @@ "lint:js": "eslint \"*.{js,md}\" \"./packages/**/**/*.{js,md}\" \"./test/*.js\" \"./www/**/**/*.{js,md}\"", "lint:ts": "eslint \"./packages/**/**/*.ts\"", "lint:css": "stylelint \"./www/**/*.js\", \"./www/**/*.css\"", - "lint": "ls-lint && yarn lint:js && yarn lint:ts && yarn lint:css", - "postinstall": "patch-package" + "lint": "ls-lint && yarn lint:js && yarn lint:ts && yarn lint:css" }, "resolutions": { "lit": "^2.1.1" @@ -49,7 +48,6 @@ "jsdom": "^16.5.0", "lerna": "^3.16.4", "mocha": "^9.1.3", - "patch-package": "^8.0.0", "rimraf": "^2.6.3", "stylelint": "^13.8.0", "stylelint-a11y": "^1.2.3", diff --git a/packages/cli/package.json b/packages/cli/package.json index 446cbf6ca..3bd29862c 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -52,7 +52,7 @@ "remark-rehype": "^7.0.0", "rollup": "^2.58.0", "unified": "^9.2.0", - "wc-compiler": "~0.8.0" + "wc-compiler": "~0.9.0" }, "devDependencies": { "@babel/runtime": "^7.10.4", diff --git a/packages/plugin-import-jsx/package.json b/packages/plugin-import-jsx/package.json index d313d9543..ada2a9e06 100644 --- a/packages/plugin-import-jsx/package.json +++ b/packages/plugin-import-jsx/package.json @@ -27,7 +27,7 @@ "@greenwood/cli": "^0.28.0-alpha.4" }, "dependencies": { - "wc-compiler": "~0.8.0" + "wc-compiler": "~0.9.0" }, "devDependencies": { "@greenwood/cli": "^0.29.0-alpha.5" diff --git a/patches/wc-compiler+0.8.0.patch b/patches/wc-compiler+0.8.0.patch deleted file mode 100644 index 8f0f44abf..000000000 --- a/patches/wc-compiler+0.8.0.patch +++ /dev/null @@ -1,40 +0,0 @@ -diff --git a/node_modules/wc-compiler/src/wcc.js b/node_modules/wc-compiler/src/wcc.js -index b27278f..9f6c6c5 100644 ---- a/node_modules/wc-compiler/src/wcc.js -+++ b/node_modules/wc-compiler/src/wcc.js -@@ -126,7 +126,7 @@ async function getTagName(moduleURL) { - return tagName; - } - --async function initializeCustomElement(elementURL, tagName, attrs = [], definitions = [], isEntry) { -+async function initializeCustomElement(elementURL, tagName, attrs = [], definitions = [], isEntry, props = {}) { - if (!tagName) { - const depth = isEntry ? 1 : 0; - registerDependencies(elementURL, definitions, depth); -@@ -137,11 +137,9 @@ async function initializeCustomElement(elementURL, tagName, attrs = [], definiti - const element = tagName - ? customElements.get(tagName) - : (await import(pathname)).default; -- const dataLoader = (await import(pathname)).getData; -- const data = dataLoader ? await dataLoader() : {}; - - if (element) { -- const elementInstance = new element(data); // eslint-disable-line new-cap -+ const elementInstance = new element(props); // eslint-disable-line new-cap - - attrs.forEach((attr) => { - elementInstance.setAttribute(attr.name, attr.value); -@@ -160,11 +158,11 @@ async function initializeCustomElement(elementURL, tagName, attrs = [], definiti - } - } - --async function renderToString(elementURL, wrappingEntryTag = true) { -+async function renderToString(elementURL, wrappingEntryTag = true, props = {}) { - const definitions = []; - const elementTagName = wrappingEntryTag && await getTagName(elementURL); - const isEntry = !!elementTagName; -- const elementInstance = await initializeCustomElement(elementURL, undefined, undefined, definitions, isEntry); -+ const elementInstance = await initializeCustomElement(elementURL, undefined, undefined, definitions, isEntry, props); - - const elementHtml = elementInstance.shadowRoot - ? elementInstance.getInnerHTML({ includeShadowRoots: true }) diff --git a/yarn.lock b/yarn.lock index a04b3beb6..6e47d4c88 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4412,11 +4412,6 @@ merge-options "^3.0.4" p-event "^5.0.1" -"@yarnpkg/lockfile@^1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz#e77a97fbd345b76d83245edcd17d393b1b41fb31" - integrity sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ== - "@zkochan/cmd-shim@^3.1.0": version "3.1.0" resolved "https://registry.yarnpkg.com/@zkochan/cmd-shim/-/cmd-shim-3.1.0.tgz#2ab8ed81f5bb5452a85f25758eb9b8681982fd2e" @@ -5126,11 +5121,6 @@ asynckit@^0.4.0: resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= -at-least-node@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2" - integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg== - atob-lite@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/atob-lite/-/atob-lite-2.0.0.tgz#0fef5ad46f1bd7a8502c65727f0367d5ee43d696" @@ -5926,7 +5916,7 @@ chownr@^2.0.0: resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece" integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ== -ci-info@3.8.0, ci-info@^3.2.0, ci-info@^3.7.0: +ci-info@3.8.0, ci-info@^3.2.0: version "3.8.0" resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.8.0.tgz#81408265a5380c929f0bc665d62256628ce9ef91" integrity sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw== @@ -8250,13 +8240,6 @@ find-up@^4.0.0, find-up@^4.1.0: locate-path "^5.0.0" path-exists "^4.0.0" -find-yarn-workspace-root@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/find-yarn-workspace-root/-/find-yarn-workspace-root-2.0.0.tgz#f47fb8d239c900eb78179aa81b66673eac88f7bd" - integrity sha512-1IMnbjt4KzsQfnhnzNd8wUEgXZ44IzZaZmnLYx7D5FZlaHt2gW20Cri8Q+E/t5tIj4+epTBub+2Zxu/vNILzqQ== - dependencies: - micromatch "^4.0.2" - flat-cache@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11" @@ -8441,16 +8424,6 @@ fs-extra@^8.1.0: jsonfile "^4.0.0" universalify "^0.1.0" -fs-extra@^9.0.0: - version "9.1.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.1.0.tgz#5954460c764a8da2094ba3554bf839e6b9a7c86d" - integrity sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ== - dependencies: - at-least-node "^1.0.0" - graceful-fs "^4.2.0" - jsonfile "^6.0.1" - universalify "^2.0.0" - fs-minipass@^1.2.5: version "1.2.7" resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.7.tgz#ccff8570841e7fe4265693da88936c55aed7f7c7" @@ -10242,7 +10215,7 @@ is-word-character@^1.0.0: resolved "https://registry.yarnpkg.com/is-word-character/-/is-word-character-1.0.4.tgz#ce0e73216f98599060592f62ff31354ddbeb0230" integrity sha512-5SMO8RVennx3nZrqtKwCGyyetPE9VDba5ugvKLaD4KopPG5kR4mQ7tNt/r7feL5yt5h3lpuBbIUmCOG2eSzXHA== -is-wsl@2.2.0, is-wsl@^2.1.1, is-wsl@^2.2.0: +is-wsl@2.2.0, is-wsl@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww== @@ -10456,13 +10429,6 @@ json-stable-stringify-without-jsonify@^1.0.1: resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== -json-stable-stringify@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.2.tgz#e06f23128e0bbe342dc996ed5a19e28b57b580e0" - integrity sha512-eunSSaEnxV12z+Z73y/j5N37/In40GK4GmsSy+tEHJMxknvqnA7/djeYtAgW0GsWHUfg+847WJjKaEylk2y09g== - dependencies: - jsonify "^0.0.1" - json-stringify-safe@^5.0.1, json-stringify-safe@~5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" @@ -10485,20 +10451,6 @@ jsonfile@^4.0.0: optionalDependencies: graceful-fs "^4.1.6" -jsonfile@^6.0.1: - version "6.1.0" - resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae" - integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ== - dependencies: - universalify "^2.0.0" - optionalDependencies: - graceful-fs "^4.1.6" - -jsonify@^0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.1.tgz#2aa3111dae3d34a0f151c63f3a45d995d9420978" - integrity sha512-2/Ki0GcmuqSrgFyelQq9M05y7PS0mEwuIzrf3f1fPqkVDVRvZrPZtVSMHxdgo8Aq0sxAOb/cr2aqqA3LeWHVPg== - jsonparse@^1.2.0: version "1.3.1" resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280" @@ -10601,13 +10553,6 @@ kind-of@^6.0.0, kind-of@^6.0.2, kind-of@^6.0.3: resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== -klaw-sync@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/klaw-sync/-/klaw-sync-6.0.0.tgz#1fd2cfd56ebb6250181114f0a581167099c2b28c" - integrity sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ== - dependencies: - graceful-fs "^4.1.11" - known-css-properties@^0.20.0: version "0.20.0" resolved "https://registry.yarnpkg.com/known-css-properties/-/known-css-properties-0.20.0.tgz#0570831661b47dd835293218381166090ff60e96" @@ -12616,14 +12561,6 @@ only@~0.0.2: resolved "https://registry.yarnpkg.com/only/-/only-0.0.2.tgz#2afde84d03e50b9a8edc444e30610a70295edfb4" integrity sha1-Kv3oTQPlC5qO3EROMGEKcCle37Q= -open@^7.4.2: - version "7.4.2" - resolved "https://registry.yarnpkg.com/open/-/open-7.4.2.tgz#b8147e26dcf3e426316c730089fd71edd29c2321" - integrity sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q== - dependencies: - is-docker "^2.0.0" - is-wsl "^2.1.1" - open@^8.0.4: version "8.4.2" resolved "https://registry.yarnpkg.com/open/-/open-8.4.2.tgz#5b5ffe2a8f793dcd2aad73e550cb87b59cb084f9" @@ -13063,27 +13000,6 @@ pascalcase@^0.1.1: resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= -patch-package@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/patch-package/-/patch-package-8.0.0.tgz#d191e2f1b6e06a4624a0116bcb88edd6714ede61" - integrity sha512-da8BVIhzjtgScwDJ2TtKsfT5JFWz1hYoBl9rUQ1f38MC2HwnEIkK8VN3dKMKcP7P7bvvgzNDbfNHtx3MsQb5vA== - dependencies: - "@yarnpkg/lockfile" "^1.1.0" - chalk "^4.1.2" - ci-info "^3.7.0" - cross-spawn "^7.0.3" - find-yarn-workspace-root "^2.0.0" - fs-extra "^9.0.0" - json-stable-stringify "^1.0.2" - klaw-sync "^6.0.0" - minimist "^1.2.6" - open "^7.4.2" - rimraf "^2.6.3" - semver "^7.5.3" - slash "^2.0.0" - tmp "^0.0.33" - yaml "^2.2.2" - path-dirname@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" @@ -16673,11 +16589,6 @@ universalify@^0.1.0, universalify@^0.1.2: resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== -universalify@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717" - integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ== - unix-dgram@2.x: version "2.0.6" resolved "https://registry.yarnpkg.com/unix-dgram/-/unix-dgram-2.0.6.tgz#6d567b0eb6d7a9504e561532b598a46e34c5968b" @@ -16908,10 +16819,10 @@ wait-port@1.0.4: commander "^9.3.0" debug "^4.3.4" -wc-compiler@~0.8.0: - version "0.8.0" - resolved "https://registry.yarnpkg.com/wc-compiler/-/wc-compiler-0.8.0.tgz#1baadbdc3aff91ff1eba601e56effcb3d6dc5ea8" - integrity sha512-vkq9wcpMOTsIDgPvQYso01fQZTD2iGzKTVhO6AbbAz5bE8WUOvNAN9sPy56An26sVmMl/KNL2St5rVmFQ/lw9w== +wc-compiler@~0.9.0: + version "0.9.0" + resolved "https://registry.yarnpkg.com/wc-compiler/-/wc-compiler-0.9.0.tgz#54730bd9c3b35d3d9190ea22894df9f208e9d089" + integrity sha512-AmpkRrOVPP0SHUF/9Y9BEiHejw3K+58cjLDxj/cN3w5ptJ3ZKEICDn7v+gEmj+d7XDwwb/8PjeEzmBWjo877ew== dependencies: acorn "^8.7.0" acorn-jsx "^5.3.2" @@ -17309,11 +17220,6 @@ yaml@^2.1.3: resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.3.1.tgz#02fe0975d23cd441242aa7204e09fc28ac2ac33b" integrity sha512-2eHWfjaoXgTBC2jNM1LRef62VQa0umtvRiDSk6HSzW7RvS5YtkabJrwYLLEKWBc8a5U2PTSCs+dJjUTJdlHsWQ== -yaml@^2.2.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.3.2.tgz#f522db4313c671a0ca963a75670f1c12ea909144" - integrity sha512-N/lyzTPaJasoDmfV7YTrYCI0G/3ivm/9wdG0aHuheKowWQwGTsK0Eoiw6utmzAnI6pkJa0DUVygvp3spqqEKXg== - yargs-parser@20.2.4, yargs-parser@^20.2.3: version "20.2.4" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54" From c7edc08b6f38ba67ccd5369f861b38faa25e733f Mon Sep 17 00:00:00 2001 From: Owen Buckley Date: Fri, 27 Oct 2023 21:29:14 -0400 Subject: [PATCH 13/13] misc PR cleanup --- packages/cli/src/lifecycles/serve.js | 1 - packages/plugin-graphql/README.md | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/cli/src/lifecycles/serve.js b/packages/cli/src/lifecycles/serve.js index 42b8bee33..bb7c66c48 100644 --- a/packages/cli/src/lifecycles/serve.js +++ b/packages/cli/src/lifecycles/serve.js @@ -294,7 +294,6 @@ async function getHybridServer(compilation) { const request = transformKoaRequestIntoStandardRequest(url, ctx.request); if (!config.prerender && matchingRoute.isSSR && !matchingRoute.prerender) { - console.log('MATCHING ROUTE -> ', matchingRoute.filename); const { handler } = await import(new URL(`./__${matchingRoute.filename}`, outputDir)); const response = await handler(request, compilation); diff --git a/packages/plugin-graphql/README.md b/packages/plugin-graphql/README.md index 88351039c..21f37bc41 100644 --- a/packages/plugin-graphql/README.md +++ b/packages/plugin-graphql/README.md @@ -1,7 +1,7 @@ # @greenwood/plugin-graphql ## Overview -A plugin for Greenwood to support using [GraphQL](https://graphql.org/) to query Greenwood's [content graph](https://www.greenwoodjs.io/docs/data/) with our optoinal [pre-made queries](https://www.greenwoodjs.io/docs/menus/). It runs [**apollo-server**](https://www.apollographql.com/docs/apollo-server/) on the backend at build time and provides a **"read-only"** [**@apollo/client** _"like"_](https://www.apollographql.com/docs/react/api/core/ApolloClient/#ApolloClient.readQuery) interface for the frontend that you can use. +A plugin for Greenwood to support using [GraphQL](https://graphql.org/) to query Greenwood's [content graph](https://www.greenwoodjs.io/docs/data/) with our optional [pre-made queries](https://www.greenwoodjs.io/docs/menus/). It runs [**apollo-server**](https://www.apollographql.com/docs/apollo-server/) on the backend at build time and provides a **"read-only"** [**@apollo/client** _"like"_](https://www.apollographql.com/docs/react/api/core/ApolloClient/#ApolloClient.readQuery) interface for the frontend that you can use. > This package assumes you already have `@greenwood/cli` installed.