From 14da40702512ab951ac957e165fdf5049a4678c5 Mon Sep 17 00:00:00 2001 From: Demir Gazetic Date: Tue, 9 Jul 2024 13:45:39 +0200 Subject: [PATCH 1/4] feat(source-nodes): optimize node sourcing and transformation for improved performance - Implement concurrent fetching of pages using Promise.all to speed up data retrieval. - Refactor variable names for better readability and maintainability. - Enhance node processing logic to handle content fields more efficiently. - Ensure robust handling of datasource entries and their dimensions. - Maintain support for local assets with improved caching mechanism. - Remove unused code. - Fix linting issues. - Update README.md. --- README.md | 134 +++++++++++++++++++----------------- lib/gatsby-node.js | 168 ++++++++++++++++++++++++++------------------- lib/src/sync.js | 65 +++++++++++------- 3 files changed, 208 insertions(+), 159 deletions(-) diff --git a/README.md b/README.md index 5194e9e5a..9dbe29dd6 100644 --- a/README.md +++ b/README.md @@ -42,11 +42,11 @@ npm install gatsby-source-storyblok #### Compatibility -| Version to install | Support | -| ------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------- | -| Latest >v6 `gatsby-source-storyblok` | Modern browsers + Node 16+. [isomorphic-fetch](https://github.com/matthew-andrews/isomorphic-fetch) is implemented. Supports Gatsby 5 (React Server Components) | -| [Version 5](https://github.com/storyblok/gatsby-source-storyblok/tree/v5) `gatsby-source-storyblok@5 ` | Modern browsers + Node 16+. [isomorphic-fetch](https://github.com/matthew-andrews/isomorphic-fetch) is implemented. (Go to [v5 branch](https://github.com/storyblok/gatsby-source-storyblok/tree/v5) for Gatsby 4 and lower Gatsby version support) -| [Version 4](https://github.com/storyblok/gatsby-source-storyblok/tree/v4.2.1) `gatsby-source-storyblok@4` | Node 14 and lower Node with no Fetch API support +| Version to install | Support | +| --------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Latest >v6 `gatsby-source-storyblok` | Modern browsers + Node 16+. [isomorphic-fetch](https://github.com/matthew-andrews/isomorphic-fetch) is implemented. Supports Gatsby 5 (React Server Components) | +| [Version 5](https://github.com/storyblok/gatsby-source-storyblok/tree/v5) `gatsby-source-storyblok@5 ` | Modern browsers + Node 16+. [isomorphic-fetch](https://github.com/matthew-andrews/isomorphic-fetch) is implemented. (Go to [v5 branch](https://github.com/storyblok/gatsby-source-storyblok/tree/v5) for Gatsby 4 and lower Gatsby version support) | +| [Version 4](https://github.com/storyblok/gatsby-source-storyblok/tree/v4.2.1) `gatsby-source-storyblok@4` | Node 14 and lower Node with no Fetch API support | ### Initialization @@ -111,6 +111,7 @@ That's it! All the features are enabled for you: the _API Client_ for interactin #### Region parameter Possible values: + - `eu` (default): For spaces created in EU - `us` : For spaces created in the US - `ap`: For spaces created in Australia @@ -123,7 +124,7 @@ Full example for a space created in the US: storyblokInit({ accessToken: "", apiOptions: { - region: 'us' + region: "us", }, }); ``` @@ -145,21 +146,22 @@ Query data from GraphQL: `src/pages/index.tsx` ```js -import { StoryblokStory } from "gatsby-source-storyblok" +import { StoryblokStory } from "gatsby-source-storyblok"; -import Layout from "../components/layout" +import Layout from "../components/layout"; const IndexPage = ({ data }) => { - if (typeof data.storyblokEntry.content === "string") data.storyblokEntry.content = JSON.parse(data.storyblokEntry.content); + if (typeof data.storyblokEntry.content === "string") + data.storyblokEntry.content = JSON.parse(data.storyblokEntry.content); return ( - ) -} + ); +}; -export default IndexPage +export default IndexPage; export const query = graphql` query HomeQuery { @@ -168,7 +170,7 @@ export const query = graphql` full_slug } } -` +`; ``` > Note: if you don't use `apiPlugin`, you can use your prefered method or function to fetch your data. @@ -185,8 +187,9 @@ Use `` to get the new story every time is triggered a `change` bridgeOptions={{ resolveRelations: ["Article.author"], resolveLinks: "url", - preventClicks: true - }} /> + preventClicks: true, + }} +/> ``` For every component you've defined in your Storyblok space, call the `storyblokEditable` function with the blok content: @@ -271,12 +274,16 @@ sbBridge.on(["input", "published", "change"], (event) => { ``` #### Rendering Rich Text + You can easily render rich text by using the `renderRichText` function that comes with `gatsby-source-storyblok`: + ```js import { renderRichText } from "gatsby-source-storyblok"; const renderedRichText = renderRichText(blok.richtext); ``` + You can set a **custom Schema and component resolver globally** at init time by using the `richText` init option: + ```js import { RichTextSchema, storyblokInit } from "gatsby-source-storyblok"; import cloneDeep from "clone-deep"; @@ -298,7 +305,9 @@ storyblokInit({ }, }); ``` + You can also set a **custom Schema and component resolver only once** by passing the options as the second parameter to `renderRichText` function: + ```js import { renderRichText } from "gatsby-source-storyblok"; renderRichText(blok.richTextField, { @@ -318,15 +327,15 @@ renderRichText(blok.richTextField, { ### Gatsby feature references ### Partial Hydration (RSC) + To enable Partial Hydration, you need to set the `PARTIAL_HYDRATION` flag to `true` in `gatsby-config` file. Here is an example of the usage: ```js module.exports = { flags: { - PARTIAL_HYDRATION: true - } -} - + PARTIAL_HYDRATION: true, + }, +}; ``` When enabling Partial Hydration, all components act as server component by default. For more details such as benefits in terms of performance, please refer to the [Gatsby docs](https://www.gatsbyjs.com/docs/how-to/performance/partial-hydration/). @@ -336,10 +345,12 @@ To define a component to act as a client component, use `"use client"` directive `layout.jsx` ```js -"use client" // Required for Partial Hydration, client components (RSC) -import configuration from '../../gatsby-config' +"use client"; // Required for Partial Hydration, client components (RSC) +import configuration from "../../gatsby-config"; -const sbConfig = configuration.plugins.find((item) => item.resolve === 'gatsby-source-storyblok') +const sbConfig = configuration.plugins.find( + (item) => item.resolve === "gatsby-source-storyblok" +); storyblokInit({ // ... @@ -353,25 +364,25 @@ storyblokInit({ You need to set the `localAssets` option to `true`. Here is an example of the usage: ```js -import { graphql } from "gatsby" -import { GatsbyImage, getImage } from "gatsby-plugin-image" +import { graphql } from "gatsby"; +import { GatsbyImage, getImage } from "gatsby-plugin-image"; function BlogPost({ data }) { - const image = getImage(data.file) + const image = getImage(data.file); return (
- ) + ); } export const pageQuery = graphql` query { - file(name: {eq: "demo"}) { + file(name: { eq: "demo" }) { absolutePath url childImageSharp { - gatsbyImageData( + gatsbyImageData( width: 200 placeholder: BLURRED formats: [AUTO, WEBP, AVIF] @@ -379,7 +390,7 @@ export const pageQuery = graphql` } } } -` +`; ``` #### With Gatsby's createPages @@ -392,36 +403,36 @@ For more info regarding `createPages` see the Gatsby docs: [docs/reference/confi import { StoryblokStory } from "gatsby-source-storyblok"; import Layout from "../components/layout"; -export default function StoryblokEntry ({ data }) { +export default function StoryblokEntry({ data }) { return ( - ) + ); } export const query = graphql` - query($slug: String!) { + query ($slug: String!) { storyblokEntry(full_slug: { eq: $full_slug }) { internalId name full_slug } } -` +`; ``` 3a. After this, you need to create the pages for your application. For this, edit your `gatsby-node.js`. ```js -const path = require('path') +const path = require("path"); exports.createPages = async ({ graphql, actions }) => { - const storyblokEntry = path.resolve('src/templates/storyblok-entry.js') + const storyblokEntry = path.resolve("src/templates/storyblok-entry.js"); // querying the storyblok data from GraphQL data layer - const { data } = await graphql( - `query { + const { data } = await graphql(` + query { allStoryblokEntry { edges { node { @@ -430,40 +441,37 @@ exports.createPages = async ({ graphql, actions }) => { } } } - }` - ) + } + `); // creating pages using createPage function like described in the documentation // https://www.gatsbyjs.org/docs/programmatically-create-pages-from-data/#creating-pages - data.allStoryblokEntry.edges.forEach(edge => { - const full_slug = edge.node.full_slug + data.allStoryblokEntry.edges.forEach((edge) => { + const full_slug = edge.node.full_slug; actions.createPage({ path: full_slug, component: storyblokEntry, context: { - slug: full_slug + slug: full_slug, }, - }) - }) -} + }); + }); +}; ``` - #### With Gatsby's File System Routes API For more info regarding The File System Routes API see the Gatsby docs: [docs/reference/routing/file-system-route-api/](https://www.gatsbyjs.com/docs/reference/routing/file-system-route-api/) 2b. Create a collection route inside `src/pages` - ``` |-- src |-- pages |-- {storyblokEntry.full_slug}.js ``` - 3b. Gatsby will use ths page template for each `storyblokEntry` ```js @@ -471,12 +479,12 @@ import { StoryblokStory } from "gatsby-source-storyblok"; import Layout from "../components/layout"; -export default function StoryblokEntry ({ data }) { +export default function StoryblokEntry({ data }) { return ( - ) + ); } export const query = graphql` @@ -487,7 +495,7 @@ export const query = graphql` full_slug } } -` +`; ``` #### The options object in details @@ -506,13 +514,15 @@ export const query = graphql` } ``` -* `accessToken`: Your Storyblok draft token -* `version`: 'draft' or 'published' -* `timeout`: Optionally provide a timeout for the api request -* `resolveLinks`: This will automatically resolve internal links of the multilink field type. If the value is `story` the whole story object will be included. If the value is `url` only uuid, id, name, path, slug and url (url is a computed property which returns the "Real path" if defined to use it for navigation links) will be included. -* `resolveRelations`: Resolve relationships to other Stories (in the first level of nesting) of a multi-option or single-option field-type. Provide the field key(s) as array to resolve specific fields. Example: ['article.related_articles', 'article.author']. -* `includeLinks`: If 'true' you can query links by allStoryblokLinkEntry. The links query lets you create a dynamic navigation tree as it includes also content folders. -* `languages`: An array of strings that will be used in languages request instead of languages in space settings. Use it to only load the languages that you want to. +- `accessToken`: Your Storyblok draft token +- `version`: 'draft' or 'published' +- `timeout`: Optionally provide a timeout for the api request +- `resolveLinks`: This will automatically resolve internal links of the multilink field type. If the value is `story` the whole story object will be included. If the value is `url` only uuid, id, name, path, slug and url (url is a computed property which returns the "Real path" if defined to use it for navigation links) will be included. +- `resolveRelations`: Resolve relationships to other Stories (in the first level of nesting) of a multi-option or single-option field-type. Provide the field key(s) as array to resolve specific fields. Example: ['article.related_articles', 'article.author']. +- `includeLinks`: If 'true' you can query links by allStoryblokLinkEntry. The links query lets you create a dynamic navigation tree as it includes also content folders. +- `languages`: An array of strings that will be used in languages request instead of languages in space settings. Use it to only load the languages that you want to. +- `includeDatasources`: If undefined or not defined, fetches all datasources. If an array of specific datasources is provided, only those datasources are fetched. If an empty array, no datasources are fetched. +- `includeTags`: If true, fetches all tags. If false, does not fetch tags. #### How to query all Content Entries @@ -575,10 +585,9 @@ If you use field level translations you can filter for a specific language using } ``` - ##### How to query filtering on content type fields -Every field of your content types is available via the prefix ```field_```. +Every field of your content types is available via the prefix `field_`. This lets you for example to query for a specific component: @@ -595,8 +604,8 @@ This lets you for example to query for a specific component: } ``` - #### How to query a single content entry + ```GraphQL { storyblokEntry(slug: { eq: "global-navi" }) { @@ -655,6 +664,7 @@ allStoryblokDatasourceEntry(filter: { data_source: { eq: "DATASOURCE_SLUG" }, da ``` #### How to query links + Use the links api to create a dynamic navigation tree. To use this query you need to add `includeLinks: true` in the plugin options. ```GraphQL @@ -697,4 +707,4 @@ allStoryblokLinkEntry { ### Contributing Please see our [contributing guidelines](https://github.com/storyblok/.github/blob/main/contributing.md) and our [code of conduct](https://www.storyblok.com/trust-center#code-of-conduct?utm_source=github.com&utm_medium=readme&utm_campaign=gatsby-source-storyblok). -This project use [semantic-release](https://semantic-release.gitbook.io/semantic-release/) for generate new versions by using commit messages and we use the Angular Convention to naming the commits. Check [this question](https://semantic-release.gitbook.io/semantic-release/support/faq#how-can-i-change-the-type-of-commits-that-trigger-a-release) about it in semantic-release FAQ. \ No newline at end of file +This project use [semantic-release](https://semantic-release.gitbook.io/semantic-release/) for generate new versions by using commit messages and we use the Angular Convention to naming the commits. Check [this question](https://semantic-release.gitbook.io/semantic-release/support/faq#how-can-i-change-the-type-of-commits-that-trigger-a-release) about it in semantic-release FAQ. diff --git a/lib/gatsby-node.js b/lib/gatsby-node.js index 839a9274b..b0bcc49fd 100644 --- a/lib/gatsby-node.js +++ b/lib/gatsby-node.js @@ -1,16 +1,16 @@ -require("isomorphic-fetch") -const { storyblokInit, apiPlugin, useStoryblokApi } = require('@storyblok/react'); -const Sync = require('./src/sync'); -const getStoryParams = require('./src/getStoryParams'); -const stringify = require('json-stringify-safe'); -const { createRemoteFileNode } = require(`gatsby-source-filesystem`); - -exports.sourceNodes = async function ({ actions }, options) { +import "isomorphic-fetch"; +import { storyblokInit, apiPlugin, useStoryblokApi } from "@storyblok/react"; +import Sync from "./src/sync"; +import getStoryParams from "./src/getStoryParams"; +import stringify from "json-stringify-safe"; +import { createRemoteFileNode } from "gatsby-source-filesystem"; + +export async function sourceNodes({ actions }, options) { const { createNode, setPluginStatus } = actions; - const { plugins, ...apiOptions } = options - storyblokInit({ use: [apiPlugin], apiOptions }) + const { ...apiOptions } = options; - const client = useStoryblokApi() + storyblokInit({ use: [apiPlugin], apiOptions }); + const client = useStoryblokApi(); Sync.init({ createNode, @@ -18,111 +18,135 @@ exports.sourceNodes = async function ({ actions }, options) { client, }); - const space = await Sync.getSpace({typePrefix: apiOptions.typePrefix}); - const languages = options.languages ? options.languages : space.language_codes; - languages.push(''); + const space = await Sync.getSpace({ typePrefix: apiOptions.typePrefix }); - for (const language of languages) { - await Sync.getAll('stories', { - node: 'StoryblokEntry', + const languages = options.languages + ? options.languages + : space.language_codes; + languages.push(""); + + const fetchStories = async (language) => { + await Sync.getAll("stories", { + node: "StoryblokEntry", params: getStoryParams(language, options), typePrefix: options.typePrefix, process: (item) => { - for (var prop in item.content) { - // eslint-disable-next-line no-prototype-builtins - if (!item.content.hasOwnProperty(prop) || ['_editable', '_uid'].indexOf(prop) > -1) { + for (const prop in item.content) { + if ( + !Object.prototype.hasOwnProperty.call(item.content, prop) || + ["_editable", "_uid"].includes(prop) + ) { continue; } const objectType = Object.prototype.toString .call(item.content[prop]) - .replace('[object ', '') - .replace(']', '') + .replace("[object ", "") + .replace("]", "") .toLowerCase(); - if (['number', 'boolean', 'string'].indexOf(objectType) === -1) { + if (!["number", "boolean", "string"].includes(objectType)) { continue; } - const type = prop == 'component' ? '' : '_' + objectType; - - item['field_' + prop + type] = item.content[prop]; + const type = prop === "component" ? "" : `_${objectType}`; + item[`field_${prop}${type}`] = item.content[prop]; } - item.content = stringify(item.content); }, }); - } + }; - await Sync.getAll('tags', { - node: 'StoryblokTag', - params: getStoryParams('', options), - process: (item) => { - item.id = item.name; - }, - }); + await Promise.all(languages.map((language) => fetchStories(language))); - if (options.includeLinks === true) { - await Sync.getAll('links', { - node: 'StoryblokLink', - params: getStoryParams('', options), + if (options.includeTags !== false) { + await Sync.getAll("tags", { + node: "StoryblokTag", + params: getStoryParams("", options), + process: (item) => { + item.id = item.name; + }, }); } - const datasources = await Sync.getAll('datasources', { - node: 'StoryblokDatasource', - typePrefix: options.typePrefix, - }); - - for (const datasource of datasources) { - const datasourceSlug = datasource.slug; + if (options.includeLinks === true) { + await Sync.getAll("links", { + node: "StoryblokLink", + params: getStoryParams("", options), + }); + } - await Sync.getAll('datasource_entries', { - node: 'StoryblokDatasourceEntry', + const fetchAllDatasources = async () => { + return await Sync.getAll("datasources", { + node: "StoryblokDatasource", typePrefix: options.typePrefix, - params: { - datasource: datasourceSlug, - }, - process: (item) => { - item.data_source_dimension = null; - item.data_source = datasourceSlug; - }, }); + }; - const datasourceDimensions = datasource.dimensions || []; + const fetchDatasourceEntries = async (datasource) => { + const datasourceSlug = datasource.slug || datasource; - for (const dimension of datasourceDimensions) { - await Sync.getAll('datasource_entries', { - node: 'StoryblokDatasourceEntry', + const fetchAllEntries = async () => { + await Sync.getAll("datasource_entries", { + node: "StoryblokDatasourceEntry", typePrefix: options.typePrefix, - params: { - datasource: datasourceSlug, - dimension: dimension.entry_value, - }, + params: { datasource: datasourceSlug }, process: (item) => { - item.data_source_dimension = dimension.entry_value; + item.data_source_dimension = null; item.data_source = datasourceSlug; }, }); - } + + const datasourceDimensions = datasource.dimensions || []; + await Promise.all( + datasourceDimensions.map((dimension) => + Sync.getAll("datasource_entries", { + node: "StoryblokDatasourceEntry", + typePrefix: options.typePrefix, + params: { + datasource: datasourceSlug, + dimension: dimension.entry_value, + }, + process: (item) => { + item.data_source_dimension = dimension.entry_value; + item.data_source = datasourceSlug; + }, + }) + ) + ); + }; + + await fetchAllEntries(); + }; + + let datasources = []; + if (options.includeDatasources === undefined) { + datasources = await fetchAllDatasources(); + } else if (options.includeDatasources.length > 0) { + datasources = options.includeDatasources; } -}; -exports.onCreateNode = async ( + await Promise.all( + datasources.map((datasource) => fetchDatasourceEntries(datasource)) + ); +} + +export async function onCreateNode( { node, actions: { createNode }, createNodeId, getCache, cache }, options -) => { +) { if (!options.localAssets) { return; } - - if (node.internal.type === 'StoryblokEntry') { + if (node.internal.type === "StoryblokEntry") { + // eslint-disable-next-line const assetRegex = /(https:\/\/a\.storyblok\.com.+?(?:\.)(\w)*)/g; let imagePaths = node.content.match(assetRegex); if (imagePaths?.length) { imagePaths.forEach(async (imagePath) => { let fileNodeID; - const mediaDataCacheKey = `sb-${imagePath.replace(/[\/|\\|https:]/g, '')}`; + // eslint-disable-next-line + const mediaDataCacheKey = `sb-${imagePath.replace(/[\/|\\|https:]/g, "")}`; const cacheMediaData = await getCache(mediaDataCacheKey); const isCached = cacheMediaData && node.cv === cacheMediaData.updatedAt; @@ -150,4 +174,4 @@ exports.onCreateNode = async ( }); } } -}; +} diff --git a/lib/src/sync.js b/lib/src/sync.js index b6cb657d4..b6c126f1c 100644 --- a/lib/src/sync.js +++ b/lib/src/sync.js @@ -1,7 +1,7 @@ -const crypto = require('crypto'); -const stringify = require('json-stringify-safe'); +import crypto from "crypto"; +import stringify from "json-stringify-safe"; -module.exports = { +export const Sync = { init({ createNode, client, setPluginStatus }) { setPluginStatus({ lastFetched: Date.now() }); this.$createNode = createNode; @@ -10,8 +10,8 @@ module.exports = { }, async getSpace(options) { - const space = await this.getOne('space', 'spaces/me', { - node: 'StoryblokSpace', + const space = await this.getOne("space", "spaces/me", { + node: "StoryblokSpace", typePrefix: options.typePrefix, }); this.$cacheVersion = space.version; @@ -20,7 +20,7 @@ module.exports = { getPage(type, page, options) { let params = { - per_page: 25, + per_page: 100, page: page, cv: this.$cacheVersion, }; @@ -30,20 +30,18 @@ module.exports = { createNode(name, item, typePrefix) { const nodeObject = this.builderNode(name, item, typePrefix); - this.$createNode(nodeObject); }, builderNode(name, item, typePrefix) { - if (name === 'StoryblokDatasourceEntry') { + if (name === "StoryblokDatasourceEntry") { return this.factoryDatasourceEntryNode(name, item, typePrefix); } - return this.factoryDefaultNode(name, item, typePrefix); }, factoryDefaultNode(name, item, typePrefix) { - const lang = item.lang || 'default'; + const lang = item.lang || "default"; const typeName = typePrefix ? `${typePrefix}${name}` : name; return Object.assign({}, item, { @@ -53,13 +51,16 @@ module.exports = { children: [], internal: { type: typeName, - contentDigest: crypto.createHash(`md5`).update(stringify(item)).digest(`hex`), + contentDigest: crypto + .createHash(`md5`) + .update(stringify(item)) + .digest(`hex`), }, }); }, factoryDatasourceEntryNode(name, item, typePrefix) { - const dimension = item.data_source_dimension || 'default'; + const dimension = item.data_source_dimension || "default"; const typeName = typePrefix ? `${typePrefix}${name}` : name; return Object.assign({}, item, { id: `${name.toLowerCase()}-${item.id}-${dimension}`, @@ -68,7 +69,10 @@ module.exports = { children: [], internal: { type: typeName, - contentDigest: crypto.createHash(`md5`).update(stringify(item)).digest(`hex`), + contentDigest: crypto + .createHash(`md5`) + .update(stringify(item)) + .digest(`hex`), }, }); }, @@ -82,26 +86,37 @@ module.exports = { async getAll(type, options) { let page = 1; - let res = await this.getPage(type, page, options); - let all = - res.data[type].constructor === Object ? Object.values(res.data[type]) : res.data[type]; - let lastPage = Math.ceil(res.total / 25); + let initialResponse = await this.getPage(type, page, options); + let allItems = + initialResponse.data[type].constructor === Object + ? Object.values(initialResponse.data[type]) + : initialResponse.data[type]; + let lastPage = Math.ceil(initialResponse.total / 25); - while (page < lastPage) { - page++; - res = await this.getPage(type, page, options); - res.data[type].forEach((item) => { - all.push(item); - }); + const fetchPromises = []; + for (let p = 2; p <= lastPage; p++) { + fetchPromises.push(this.getPage(type, p, options)); } - all.forEach((item) => { + const pageResponses = await Promise.all(fetchPromises); + + pageResponses.forEach((pageResponse) => { + const items = + pageResponse.data[type].constructor === Object + ? Object.values(pageResponse.data[type]) + : pageResponse.data[type]; + items.forEach((item) => { + allItems.push(item); + }); + }); + + allItems.forEach((item) => { if (options.process) { options.process(item); } this.createNode(options.node, item, options.typePrefix); }); - return all; + return allItems; }, }; From 35c1fe48e2656adab76b96ab2b7a5cdd6c1896b2 Mon Sep 17 00:00:00 2001 From: Demir Gazetic Date: Tue, 9 Jul 2024 16:10:16 +0200 Subject: [PATCH 2/4] chore:Revert to CommonJS Syntax for Compatibility with Gatsby --- lib/gatsby-node.js | 21 +++++++++++---------- lib/src/sync.js | 16 +++++++--------- 2 files changed, 18 insertions(+), 19 deletions(-) diff --git a/lib/gatsby-node.js b/lib/gatsby-node.js index b0bcc49fd..dfdc90530 100644 --- a/lib/gatsby-node.js +++ b/lib/gatsby-node.js @@ -1,11 +1,11 @@ -import "isomorphic-fetch"; -import { storyblokInit, apiPlugin, useStoryblokApi } from "@storyblok/react"; -import Sync from "./src/sync"; -import getStoryParams from "./src/getStoryParams"; -import stringify from "json-stringify-safe"; -import { createRemoteFileNode } from "gatsby-source-filesystem"; - -export async function sourceNodes({ actions }, options) { +require("isomorphic-fetch") +const { storyblokInit, apiPlugin, useStoryblokApi } = require("@storyblok/react"); +const Sync = require("./src/sync"); +const getStoryParams = require("./src/getStoryParams"); +const stringify = require("json-stringify-safe"); +const { createRemoteFileNode } = require(`gatsby-source-filesystem`); + +exports.sourceNodes = async function ({ actions }, options) { const { createNode, setPluginStatus } = actions; const { ...apiOptions } = options; @@ -130,10 +130,10 @@ export async function sourceNodes({ actions }, options) { ); } -export async function onCreateNode( +exports.onCreateNode = async ( { node, actions: { createNode }, createNodeId, getCache, cache }, options -) { +) => { if (!options.localAssets) { return; } @@ -175,3 +175,4 @@ export async function onCreateNode( } } } + diff --git a/lib/src/sync.js b/lib/src/sync.js index b6c126f1c..ad6b75510 100644 --- a/lib/src/sync.js +++ b/lib/src/sync.js @@ -1,7 +1,7 @@ -import crypto from "crypto"; -import stringify from "json-stringify-safe"; +const crypto = require("crypto"); +const stringify = require("json-stringify-safe"); -export const Sync = { +module.exports = { init({ createNode, client, setPluginStatus }) { setPluginStatus({ lastFetched: Date.now() }); this.$createNode = createNode; @@ -51,8 +51,7 @@ export const Sync = { children: [], internal: { type: typeName, - contentDigest: crypto - .createHash(`md5`) + contentDigest: crypto.createHash(`md5`) .update(stringify(item)) .digest(`hex`), }, @@ -69,10 +68,9 @@ export const Sync = { children: [], internal: { type: typeName, - contentDigest: crypto - .createHash(`md5`) - .update(stringify(item)) - .digest(`hex`), + contentDigest: crypto.createHash(`md5`). + update(stringify(item)). + digest(`hex`), }, }); }, From 04bb8792a7a56b52e920b6978e848ea644e1d6a6 Mon Sep 17 00:00:00 2001 From: demirgazetic Date: Wed, 24 Jul 2024 18:05:52 +0200 Subject: [PATCH 3/4] fix: missing data_source_dimension in included datasources --- lib/gatsby-node.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/gatsby-node.js b/lib/gatsby-node.js index dfdc90530..2959b5d15 100644 --- a/lib/gatsby-node.js +++ b/lib/gatsby-node.js @@ -122,7 +122,10 @@ exports.sourceNodes = async function ({ actions }, options) { if (options.includeDatasources === undefined) { datasources = await fetchAllDatasources(); } else if (options.includeDatasources.length > 0) { - datasources = options.includeDatasources; + const allDatasources = await fetchAllDatasources(); + const includeSet = new Set(options.includeDatasources); + + datasources = allDatasources.filter(datasource => includeSet.has(datasource.slug)); } await Promise.all( From 00404f6d456bf59a197d729c9377f6dc8bfbde08 Mon Sep 17 00:00:00 2001 From: demirgazetic Date: Thu, 1 Aug 2024 14:05:29 +0200 Subject: [PATCH 4/4] Refactor getAll method to use a single page variable and update pagination logic - Updated the pagination logic to use a single `page` variable for both the initial response and the for loop. - Changed the calculation of `lastPage` by dividing the total number by 100 instead of 25 to optimize the page count. --- lib/src/sync.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/src/sync.js b/lib/src/sync.js index ad6b75510..078e0ab16 100644 --- a/lib/src/sync.js +++ b/lib/src/sync.js @@ -89,11 +89,11 @@ module.exports = { initialResponse.data[type].constructor === Object ? Object.values(initialResponse.data[type]) : initialResponse.data[type]; - let lastPage = Math.ceil(initialResponse.total / 25); + let lastPage = Math.ceil(initialResponse.total / 100); const fetchPromises = []; - for (let p = 2; p <= lastPage; p++) { - fetchPromises.push(this.getPage(type, p, options)); + for (page = 2; page <= lastPage; page++) { + fetchPromises.push(this.getPage(type, page, options)); } const pageResponses = await Promise.all(fetchPromises); @@ -116,5 +116,5 @@ module.exports = { }); return allItems; - }, + } };