diff --git a/packages/gatsby-core-utils/src/service-lock.ts b/packages/gatsby-core-utils/src/service-lock.ts index 1ce4ad9087968..ac3559ecd09ee 100644 --- a/packages/gatsby-core-utils/src/service-lock.ts +++ b/packages/gatsby-core-utils/src/service-lock.ts @@ -30,7 +30,7 @@ const lockfileOptions = { stale: 5000, } -type UnlockFn = () => Promise +export type UnlockFn = () => Promise const memoryServices = {} export const createServiceLock = async ( diff --git a/packages/gatsby-recipes/src/create-types.test.js b/packages/gatsby-recipes/src/create-types.test.js index 095f83dfb8f18..54df14f67e465 100644 --- a/packages/gatsby-recipes/src/create-types.test.js +++ b/packages/gatsby-recipes/src/create-types.test.js @@ -22,6 +22,15 @@ test(`create-types`, () => { "resolve": [Function], "type": "File", }, + "createGatsbyPage": Object { + "args": Object { + "gatsbyPage": Object { + "type": "GatsbyPageInput", + }, + }, + "resolve": [Function], + "type": "GatsbyPage", + }, "createGatsbyPlugin": Object { "args": Object { "gatsbyPlugin": Object { @@ -94,6 +103,15 @@ test(`create-types`, () => { "resolve": [Function], "type": "File", }, + "destroyGatsbyPage": Object { + "args": Object { + "gatsbyPage": Object { + "type": "GatsbyPageInput", + }, + }, + "resolve": [Function], + "type": "GatsbyPage", + }, "destroyGatsbyPlugin": Object { "args": Object { "gatsbyPlugin": Object { @@ -166,6 +184,15 @@ test(`create-types`, () => { "resolve": [Function], "type": "File", }, + "updateGatsbyPage": Object { + "args": Object { + "gatsbyPage": Object { + "type": "GatsbyPageInput", + }, + }, + "resolve": [Function], + "type": "GatsbyPage", + }, "updateGatsbyPlugin": Object { "args": Object { "gatsbyPlugin": Object { @@ -224,6 +251,10 @@ test(`create-types`, () => { `) expect(result.queryTypes).toMatchInlineSnapshot(` Object { + "allGatsbyPage": Object { + "resolve": [Function], + "type": "GatsbyPageConnection", + }, "allGatsbyPlugin": Object { "resolve": [Function], "type": "GatsbyPluginConnection", @@ -258,6 +289,15 @@ test(`create-types`, () => { "resolve": [Function], "type": "File", }, + "gatsbyPage": Object { + "args": Object { + "id": Object { + "type": "String", + }, + }, + "resolve": [Function], + "type": "GatsbyPage", + }, "gatsbyPlugin": Object { "args": Object { "id": Object { diff --git a/packages/gatsby-recipes/src/providers/gatsby/page.js b/packages/gatsby-recipes/src/providers/gatsby/page.js new file mode 100644 index 0000000000000..5fc0fa4ca2d51 --- /dev/null +++ b/packages/gatsby-recipes/src/providers/gatsby/page.js @@ -0,0 +1,108 @@ +const Joi = require(`@hapi/joi`) +const { getService } = require(`gatsby-core-utils/dist/service-lock`) +const fetch = require(`node-fetch`) + +const { REQUIRES_KEYS } = require(`./utils/constants`) +const resourceSchema = require(`../resource-schema`) + +module.exports.create = () => {} +module.exports.update = () => {} +module.exports.read = async ({ root }, id) => { + const result = await queryDevelopAPI( + { root }, + ` + { + sitePage(id: { eq: "${id}" }) { + path + component + internalComponentName + componentChunkName + matchPath + id + componentPath + isCreatedByStatefulCreatePages + } + } + ` + ) + + return result.data.sitePage +} +module.exports.destroy = () => {} +module.exports.config = {} + +const queryDevelopAPI = async ({ root }, query) => { + const { port } = await getService(root, `developproxy`) + + const res = await fetch(`http://localhost:${port}/___graphql`, { + method: `POST`, + body: JSON.stringify({ + query, + }), + headers: { + Accept: `application/json`, + "Content-Type": `application/json`, + }, + }) + const body = await res.json() + + return body +} + +module.exports.all = async ({ root }) => { + const result = await queryDevelopAPI( + { root }, + ` + { + allSitePage { + nodes { + path + component + internalComponentName + componentChunkName + matchPath + id + componentPath + isCreatedByStatefulCreatePages + } + } + } + ` + ) + + return result.data.allSitePage.nodes +} +const schema = { + internalComponentName: Joi.string(), + path: Joi.string(), + matchPath: Joi.string().optional(), + component: Joi.string(), + componentChunkName: Joi.string(), + isCreatedByStatefulCreatePages: Joi.boolean(), + pluginCreatorId: Joi.string(), + componentPath: Joi.string(), + ...resourceSchema, +} + +const validate = resource => { + if (REQUIRES_KEYS.includes(resource.name) && !resource.key) { + return { + error: `${resource.name} requires a key to be set`, + } + } + + if (resource.key && resource.key === resource.name) { + return { + error: `${resource.name} requires a key to be different than the plugin name`, + } + } + + return Joi.validate(resource, schema, { abortEarly: false }) +} + +exports.schema = schema +exports.validate = validate + +module.exports.plan = async () => { + return {} +} diff --git a/packages/gatsby-recipes/src/resources.js b/packages/gatsby-recipes/src/resources.js index 6e2d2e2f12582..72ef0f29d43fe 100644 --- a/packages/gatsby-recipes/src/resources.js +++ b/packages/gatsby-recipes/src/resources.js @@ -1,5 +1,6 @@ const fileResource = require(`./providers/fs/file`) const directoryResource = require(`./providers/fs/directory`) +const gatsbyPageResource = require(`./providers/gatsby/page`) const gatsbyPluginResource = require(`./providers/gatsby/plugin`) const gatsbyShadowFileResource = require(`./providers/gatsby/shadow-file`) const npmPackageResource = require(`./providers/npm/package`) @@ -10,6 +11,7 @@ const gitIgnoreResource = require(`./providers/git/ignore`) const componentResourceMapping = { File: fileResource, Directory: directoryResource, + GatsbyPage: gatsbyPageResource, GatsbyPlugin: gatsbyPluginResource, GatsbyShadowFile: gatsbyShadowFileResource, NPMPackage: npmPackageResource, diff --git a/packages/gatsby/src/commands/develop.ts b/packages/gatsby/src/commands/develop.ts index 5d8847632d2a6..65b8cd8b71a51 100644 --- a/packages/gatsby/src/commands/develop.ts +++ b/packages/gatsby/src/commands/develop.ts @@ -9,6 +9,7 @@ import socket from "socket.io" import fs from "fs-extra" import { isCI, slash } from "gatsby-core-utils" import { createServiceLock } from "gatsby-core-utils/dist/service-lock" +import { UnlockFn } from "gatsby-core-utils/src/service-lock" import reporter from "gatsby-cli/lib/reporter" import getSslCert from "../utils/get-ssl-cert" import { startDevelopProxy } from "../utils/develop-proxy" @@ -193,18 +194,31 @@ module.exports = async (program: IProgram): Promise => { cmd(args); `) - let unlock + let unlocks: Array = [] if (!isCI()) { - unlock = await createServiceLock(program.directory, `developstatusserver`, { - port: statusServerPort, - }) + const statusUnlock = await createServiceLock( + program.directory, + `developstatusserver`, + { + port: statusServerPort, + } + ) + const developUnlock = await createServiceLock( + program.directory, + `developproxy`, + { + port: proxyPort, + } + ) - if (!unlock) { + if (!statusUnlock || !developUnlock) { console.error( `Looks like develop for this site is already running. Try visiting http://localhost:8000/ maybe?` ) process.exit(1) } + + unlocks = unlocks.concat([statusUnlock, developUnlock]) } const statusServer = http.createServer().listen(statusServerPort) @@ -303,7 +317,7 @@ module.exports = async (program: IProgram): Promise => { process.on(`beforeExit`, async () => { await Promise.all([ watcher?.close(), - unlock?.(), + ...unlocks.map(unlock => unlock()), new Promise(resolve => { statusServer.close(resolve) }),