From 1582816e175a6be902de70c10b15fbf67ab25bd5 Mon Sep 17 00:00:00 2001 From: Artem Alexeyenko Date: Fri, 4 Nov 2022 11:10:36 -0400 Subject: [PATCH 1/7] GraphQL site info service (#1227) * GraphQL site info service * some tweaks * more tweaks: debug, query * query fix for xm cloud * move template id to contstants --- packages/sitecore-jss/src/constants.ts | 2 + packages/sitecore-jss/src/debug.ts | 1 + .../src/site/graphql-siteinfo-service.test.ts | 128 +++++++++++++++++ .../src/site/graphql-siteinfo-service.ts | 131 ++++++++++++++++++ packages/sitecore-jss/src/site/index.ts | 6 + 5 files changed, 268 insertions(+) create mode 100644 packages/sitecore-jss/src/site/graphql-siteinfo-service.test.ts create mode 100644 packages/sitecore-jss/src/site/graphql-siteinfo-service.ts diff --git a/packages/sitecore-jss/src/constants.ts b/packages/sitecore-jss/src/constants.ts index fee6b3dde8..0e4f0d10e0 100644 --- a/packages/sitecore-jss/src/constants.ts +++ b/packages/sitecore-jss/src/constants.ts @@ -16,4 +16,6 @@ export const JSS_MODE = { DISCONNECTED: 'disconnected', }; +export const headlessSiteGroupingTemplate = 'E46F3AF2-39FA-4866-A157-7017C4B2A40C'; + export const siteNameError = 'The siteName cannot be empty'; diff --git a/packages/sitecore-jss/src/debug.ts b/packages/sitecore-jss/src/debug.ts index af4d5240d8..c62916210a 100644 --- a/packages/sitecore-jss/src/debug.ts +++ b/packages/sitecore-jss/src/debug.ts @@ -33,6 +33,7 @@ export default { dictionary: debug(`${rootNamespace}:dictionary`), editing: debug(`${rootNamespace}:editing`), sitemap: debug(`${rootNamespace}:sitemap`), + multisite: debug(`${rootNamespace}:multisite`), robots: debug(`${rootNamespace}:robots`), redirects: debug(`${rootNamespace}:redirects`), personalize: debug(`${rootNamespace}:personalize`), diff --git a/packages/sitecore-jss/src/site/graphql-siteinfo-service.test.ts b/packages/sitecore-jss/src/site/graphql-siteinfo-service.test.ts new file mode 100644 index 0000000000..3c842bb0b8 --- /dev/null +++ b/packages/sitecore-jss/src/site/graphql-siteinfo-service.test.ts @@ -0,0 +1,128 @@ +import { expect } from 'chai'; +import nock from 'nock'; +import { GraphQLSiteInfoService } from './graphql-siteinfo-service'; + +describe('GraphQLSiteInfoService', () => { + const endpoint = 'http://site'; + const apiKey = 'some-api-key'; + const nonEmptyResponse = { + data: { + search: { + results: [ + { + name: 'site 51', + hostName: { + value: 'restricted.gov', + }, + virtualFolder: { + value: '/aliens', + }, + language: { + value: 'en', + }, + }, + { + name: 'public', + hostName: { + value: 'pr.showercurtains.org', + }, + virtualFolder: { + value: '/we-are-open', + }, + language: { + value: '', + }, + }, + ], + }, + }, + }; + const emptyResponse = { + data: { + search: { + results: [], + }, + }, + }; + + afterEach(() => { + nock.cleanAll(); + }); + + const mockSiteInfoRequest = () => { + nock(endpoint) + .post('/') + .reply(200, nonEmptyResponse); + }; + + it('should return correct result', async () => { + mockSiteInfoRequest(); + const service = new GraphQLSiteInfoService({ apiKey: apiKey, endpoint: endpoint }); + const result = await service.fetchSiteInfo(); + expect(result).to.be.deep.equal([ + { + name: 'site 51', + hostName: 'restricted.gov', + virtualFolder: '/aliens', + language: 'en', + }, + { + name: 'public', + hostName: 'pr.showercurtains.org', + virtualFolder: '/we-are-open', + language: '', + }, + ]); + }); + + it('should return empty array when empty result received', async () => { + nock(endpoint) + .post('/') + .reply(200, emptyResponse); + const service = new GraphQLSiteInfoService({ apiKey: apiKey, endpoint: endpoint }); + const result = await service.fetchSiteInfo(); + expect(result).to.deep.equal([]); + }); + + it('should use caching by default', async () => { + mockSiteInfoRequest(); + const service = new GraphQLSiteInfoService({ apiKey: apiKey, endpoint: endpoint }); + const result = await service.fetchSiteInfo(); + nock.cleanAll(); + nock(endpoint) + .post('/') + .reply(200, emptyResponse); + const resultCached = await service.fetchSiteInfo(); + expect(resultCached).to.deep.equal(result); + }); + + it('should be possible to disable cache', async () => { + mockSiteInfoRequest(); + const service = new GraphQLSiteInfoService({ + apiKey: apiKey, + endpoint: endpoint, + cacheEnabled: false, + }); + const result = await service.fetchSiteInfo(); + expect(result).to.be.deep.equal([ + { + name: 'site 51', + hostName: 'restricted.gov', + virtualFolder: '/aliens', + language: 'en', + }, + { + name: 'public', + hostName: 'pr.showercurtains.org', + virtualFolder: '/we-are-open', + language: '', + }, + ]); + nock.cleanAll(); + nock(endpoint) + .post('/') + .reply(200, emptyResponse); + const resultCached = await service.fetchSiteInfo(); + expect(resultCached).to.deep.equal([]); + }); +}); diff --git a/packages/sitecore-jss/src/site/graphql-siteinfo-service.ts b/packages/sitecore-jss/src/site/graphql-siteinfo-service.ts new file mode 100644 index 0000000000..80a4b82613 --- /dev/null +++ b/packages/sitecore-jss/src/site/graphql-siteinfo-service.ts @@ -0,0 +1,131 @@ +import { GraphQLClient, GraphQLRequestClient } from '../graphql'; +import debug from '../debug'; +import { CacheClient, CacheOptions, MemoryCacheClient } from '../cache-client'; +import { headlessSiteGroupingTemplate } from '../constants'; + +const defaultQuery = /* GraphQL */ ` + { + search( + where: { name: "_templates", value: "${headlessSiteGroupingTemplate}", operator: CONTAINS } + ) { + results { + ... on Item { + name + hostName: field(name: "Hostname") { + value + } + virtualFolder: field(name: "VirtualFolder") { + value + } + language: field(name: "Language") { + value + } + } + } + } +} +`; + +export type SiteInfo = { + name: string; + hostName: string; + virtualFolder: string; + language: string; +}; + +export type GraphQLSiteInfoServiceConfig = CacheOptions & { + /** + * Your Graphql endpoint + */ + endpoint: string; + /** + * The API key to use for authentication + */ + apiKey: string; +}; + +type GraphQLSiteInfoResponse = { + search: { + results: GraphQLSiteInfoResult[]; + }; +}; + +type GraphQLSiteInfoResult = { + name: string; + hostName: { + value: string; + }; + virtualFolder: { + value: string; + }; + language: { + value: string; + }; +}; + +export class GraphQLSiteInfoService { + private graphQLClient: GraphQLClient; + private cache: CacheClient; + + protected get query(): string { + return defaultQuery; + } + + /** + * Creates an instance of graphQL service to retrieve site configuration list from Sitecore + * @param {GraphQLSiteInfoServiceConfig} config instance + */ + constructor(private config: GraphQLSiteInfoServiceConfig) { + this.graphQLClient = this.getGraphQLClient(); + this.cache = this.getCacheClient(); + } + + async fetchSiteInfo(): Promise { + const cachedResult = this.cache.getCacheValue(this.getCacheKey()); + if (cachedResult) { + return cachedResult; + } + + const response = await this.graphQLClient.request(this.query); + const result = response?.search?.results?.reduce((result, current) => { + result.push({ + name: current.name, + hostName: current.hostName.value, + virtualFolder: current.virtualFolder.value, + language: current.language.value, + }); + return result; + }, []); + this.cache.setCacheValue(this.getCacheKey(), result); + return result; + } + + /** + * Gets cache client implementation + * Override this method if custom cache needs to be used + * @returns CacheClient instance + */ + protected getCacheClient(): CacheClient { + return new MemoryCacheClient({ + cacheEnabled: this.config.cacheEnabled ?? true, + cacheTimeout: this.config.cacheTimeout ?? 10, + }); + } + + /** + * Gets a GraphQL client that can make requests to the API. Uses graphql-request as the default + * library for fetching graphql data (@see GraphQLRequestClient). Override this method if you + * want to use something else. + * @returns {GraphQLClient} implementation + */ + protected getGraphQLClient(): GraphQLClient { + return new GraphQLRequestClient(this.config.endpoint, { + apiKey: this.config.apiKey, + debugger: debug.multisite, + }); + } + + private getCacheKey(): string { + return 'siteinfo-service-cache'; + } +} diff --git a/packages/sitecore-jss/src/site/index.ts b/packages/sitecore-jss/src/site/index.ts index de04de1d68..4ec786780c 100644 --- a/packages/sitecore-jss/src/site/index.ts +++ b/packages/sitecore-jss/src/site/index.ts @@ -24,3 +24,9 @@ export { GraphQLErrorPagesService, GraphQLErrorPagesServiceConfig, } from './graphql-error-pages-service'; + +export { + SiteInfo, + GraphQLSiteInfoService, + GraphQLSiteInfoServiceConfig, +} from './graphql-siteinfo-service'; From ca9ae905d07ea01cd529031909844f4f801b895a Mon Sep 17 00:00:00 2001 From: Illia Kovalenko <23364749+illiakovalenko@users.noreply.github.com> Date: Fri, 4 Nov 2022 17:12:34 +0200 Subject: [PATCH 2/7] [Next.js][Multi-site] Dynamic site resolver (#1224) * [Next.js][Multi-site] Dynamic site resolver * Use SiteInfo from graphql-siteinfo-service Co-authored-by: Adam Brauer <400763+ambrauer@users.noreply.github.com> --- packages/sitecore-jss/src/site/index.ts | 1 + .../src/site/site-resolver.test.ts | 37 +++++++++++++++++++ .../sitecore-jss/src/site/site-resolver.ts | 17 +++++++++ 3 files changed, 55 insertions(+) create mode 100644 packages/sitecore-jss/src/site/site-resolver.test.ts create mode 100644 packages/sitecore-jss/src/site/site-resolver.ts diff --git a/packages/sitecore-jss/src/site/index.ts b/packages/sitecore-jss/src/site/index.ts index 4ec786780c..f54ffc4db8 100644 --- a/packages/sitecore-jss/src/site/index.ts +++ b/packages/sitecore-jss/src/site/index.ts @@ -25,6 +25,7 @@ export { GraphQLErrorPagesServiceConfig, } from './graphql-error-pages-service'; +export { SiteResolver } from './site-resolver'; export { SiteInfo, GraphQLSiteInfoService, diff --git a/packages/sitecore-jss/src/site/site-resolver.test.ts b/packages/sitecore-jss/src/site/site-resolver.test.ts new file mode 100644 index 0000000000..d5c2d7aaf6 --- /dev/null +++ b/packages/sitecore-jss/src/site/site-resolver.test.ts @@ -0,0 +1,37 @@ +import { expect } from 'chai'; +import { SiteResolver } from './site-resolver'; + +describe('SiteResolver', () => { + const sitesInfo = [ + { + name: 'cat', + hostName: 'supercat.com', + virtualFolder: '/north', + language: 'en', + }, + { + name: 'dog', + hostName: 'superdog.com', + virtualFolder: '/south', + language: 'da-DK', + }, + ]; + + it('should resolve site name', () => { + const siteName = SiteResolver.resolve('superdog.com', sitesInfo); + + expect(siteName).to.equal('dog'); + }); + + it('should return custom fallback site name', () => { + const siteName = SiteResolver.resolve('superanimal.com', sitesInfo, 'animal'); + + expect(siteName).to.equal('animal'); + }); + + it('should return default fallback site name', () => { + const siteName = SiteResolver.resolve('superanimal.com', sitesInfo); + + expect(siteName).to.equal('website'); + }); +}); diff --git a/packages/sitecore-jss/src/site/site-resolver.ts b/packages/sitecore-jss/src/site/site-resolver.ts new file mode 100644 index 0000000000..25137aad2f --- /dev/null +++ b/packages/sitecore-jss/src/site/site-resolver.ts @@ -0,0 +1,17 @@ +import { SiteInfo } from './graphql-siteinfo-service'; + +// This resolver is used to determine site name based on the provided hostname +export class SiteResolver { + /** + * Resolve siteName by hostName + * @param {string} hostName + * @param {SiteInfo[]} sitesInfo + * @param {string} [fallbackSiteName] siteName to be returned in case siteName is not found + * @returns {string} siteName + */ + static resolve = (hostName: string, sitesInfo: SiteInfo[], fallbackSiteName?: string): string => { + const siteInfo = sitesInfo.find((info) => info.hostName === hostName); + + return siteInfo?.name || fallbackSiteName || 'website'; + }; +} From 5a7103f0736aef7c6bd959d41a05b82c9e1970d1 Mon Sep 17 00:00:00 2001 From: Adam Brauer <400763+ambrauer@users.noreply.github.com> Date: Thu, 22 Dec 2022 14:39:40 -0600 Subject: [PATCH 3/7] Plugin approach for JSS config generation. Added multisite plugin to set the "sites" prop. --- .../scripts/config/plugins/multisite.ts | 43 ++++++++ .../scripts/config/plugins/disconnected.ts | 30 ++++++ .../src/templates/nextjs/package.json | 1 + .../src/templates/nextjs/scripts/bootstrap.ts | 36 ++----- .../templates/nextjs/scripts/config/index.ts | 39 +++++++ .../nextjs/scripts/config/plugins/computed.ts | 15 +++ .../scripts/config/plugins/package-json.ts | 18 ++++ .../scripts/config/plugins/scjssconfig.ts | 25 +++++ .../nextjs/scripts/generate-config.ts | 101 +++++++----------- .../nextjs/scripts/generate-plugins.ts | 8 +- .../templates/nextjs/scripts/temp/.gitignore | 2 + .../templates/nextjs/tsconfig.scripts.json | 5 + packages/sitecore-jss-nextjs/src/index.ts | 3 + .../src/site/graphql-siteinfo-service.ts | 17 +-- 14 files changed, 241 insertions(+), 102 deletions(-) create mode 100644 packages/create-sitecore-jss/src/templates/nextjs-multisite/scripts/config/plugins/multisite.ts create mode 100644 packages/create-sitecore-jss/src/templates/nextjs-styleguide/scripts/config/plugins/disconnected.ts create mode 100644 packages/create-sitecore-jss/src/templates/nextjs/scripts/config/index.ts create mode 100644 packages/create-sitecore-jss/src/templates/nextjs/scripts/config/plugins/computed.ts create mode 100644 packages/create-sitecore-jss/src/templates/nextjs/scripts/config/plugins/package-json.ts create mode 100644 packages/create-sitecore-jss/src/templates/nextjs/scripts/config/plugins/scjssconfig.ts create mode 100644 packages/create-sitecore-jss/src/templates/nextjs/scripts/temp/.gitignore diff --git a/packages/create-sitecore-jss/src/templates/nextjs-multisite/scripts/config/plugins/multisite.ts b/packages/create-sitecore-jss/src/templates/nextjs-multisite/scripts/config/plugins/multisite.ts new file mode 100644 index 0000000000..152976865f --- /dev/null +++ b/packages/create-sitecore-jss/src/templates/nextjs-multisite/scripts/config/plugins/multisite.ts @@ -0,0 +1,43 @@ +import 'dotenv/config'; +import chalk from 'chalk'; +import { ConfigPlugin, JssConfig } from '../../../../nextjs/scripts/config'; +import { GraphQLSiteInfoService, SiteInfo } from '@sitecore-jss/sitecore-jss-nextjs'; + +/** + * This plugin will set the "sites" config prop. + * By default this will attempt to fetch site information directly from Sitecore (using the GraphQLSiteInfoService). + * You could easily modify this to fetch from another source such as a static JSON file instead. + */ +class MultisitePlugin implements ConfigPlugin { + order = 4; + + async exec(config: JssConfig) { + let sites: SiteInfo[] = []; + const endpoint = process.env.GRAPH_QL_ENDPOINT || config.graphQLEndpoint; + const apiKey = process.env.SITECORE_API_KEY || config.sitecoreApiKey; + + if (!endpoint || !apiKey) { + console.warn( + chalk.yellow('Skipping site information fetch (missing GraphQL connection details)') + ); + } else { + console.log(`Fetching site information from ${endpoint}`); + try { + const siteInfoService = new GraphQLSiteInfoService({ + endpoint, + apiKey, + }); + sites = await siteInfoService.fetchSiteInfo(); + } catch (error) { + console.error(chalk.red('Error fetching site information')); + console.error(error); + } + } + + return Object.assign({}, config, { + sites: JSON.stringify(sites), + }); + } +} + +export const multisitePlugin = new MultisitePlugin(); diff --git a/packages/create-sitecore-jss/src/templates/nextjs-styleguide/scripts/config/plugins/disconnected.ts b/packages/create-sitecore-jss/src/templates/nextjs-styleguide/scripts/config/plugins/disconnected.ts new file mode 100644 index 0000000000..71e8f76358 --- /dev/null +++ b/packages/create-sitecore-jss/src/templates/nextjs-styleguide/scripts/config/plugins/disconnected.ts @@ -0,0 +1,30 @@ +import 'dotenv/config'; +import chalk from 'chalk'; +import { constants } from '@sitecore-jss/sitecore-jss-nextjs'; +import { ConfigPlugin, JssConfig } from '../../../../nextjs/scripts/config'; + +class DisconnectedPlugin implements ConfigPlugin { + order = 4; + + async exec(config: JssConfig) { + const disconnected = process.env.JSS_MODE === constants.JSS_MODE.DISCONNECTED; + + if (!disconnected) return config; + + if (process.env.FETCH_WITH === constants.FETCH_WITH.GRAPHQL) { + throw new Error( + chalk.red( + 'GraphQL requests to Dictionary and Layout services are not supported in disconnected mode.' + ) + ); + } + + const port = process.env.PORT || 3000; + + return Object.assign({}, config, { + sitecoreApiHost: `http://localhost:${port}`, + }); + } +} + +export const disconnectedPlugin = new DisconnectedPlugin(); diff --git a/packages/create-sitecore-jss/src/templates/nextjs/package.json b/packages/create-sitecore-jss/src/templates/nextjs/package.json index 4cd2a11f67..1330a5af2f 100644 --- a/packages/create-sitecore-jss/src/templates/nextjs/package.json +++ b/packages/create-sitecore-jss/src/templates/nextjs/package.json @@ -67,6 +67,7 @@ "npm-run-all": "~4.1.5", "prettier": "^2.1.2", "ts-node": "^9.0.0", + "tsconfig-paths": "^4.1.1", "typescript": "~4.3.5", "yaml-loader": "^0.6.0" }, diff --git a/packages/create-sitecore-jss/src/templates/nextjs/scripts/bootstrap.ts b/packages/create-sitecore-jss/src/templates/nextjs/scripts/bootstrap.ts index 3c9085a10a..b8ada06806 100644 --- a/packages/create-sitecore-jss/src/templates/nextjs/scripts/bootstrap.ts +++ b/packages/create-sitecore-jss/src/templates/nextjs/scripts/bootstrap.ts @@ -1,41 +1,21 @@ -import 'dotenv/config'; -import { generateConfig } from './generate-config'; -import { constants } from '@sitecore-jss/sitecore-jss-nextjs'; -import chalk from 'chalk'; /* BOOTSTRAPPING The bootstrap process runs before build, and generates JS that needs to be - included into the build - specifically, the component name to component mapping, - and the global config module. + included into the build - specifically, plugins, the global config module, + and the component name to component mapping. */ -const disconnected = process.env.JSS_MODE === constants.JSS_MODE.DISCONNECTED; /* - CONFIG GENERATION - Generates the /src/temp/config.js file which contains runtime configuration - that the app can import and use. + PLUGINS GENERATION */ -const port = process.env.PORT || 3000; -const configOverride: { [key: string]: string } = {}; -if (disconnected) { - if (process.env.FETCH_WITH === constants.FETCH_WITH.GRAPHQL) { - throw new Error( - chalk.red( - 'GraphQL requests to Dictionary and Layout services are not supported in disconnected mode.' - ) - ); - } - configOverride.sitecoreApiHost = `http://localhost:${port}`; -} - -generateConfig(configOverride); +import './generate-plugins'; /* - COMPONENT FACTORY GENERATION + CONFIG GENERATION */ -import './generate-component-factory'; +import './generate-config'; /* - PLUGINS GENERATION + COMPONENT FACTORY GENERATION */ -import './generate-plugins'; +import './generate-component-factory'; diff --git a/packages/create-sitecore-jss/src/templates/nextjs/scripts/config/index.ts b/packages/create-sitecore-jss/src/templates/nextjs/scripts/config/index.ts new file mode 100644 index 0000000000..425474d0eb --- /dev/null +++ b/packages/create-sitecore-jss/src/templates/nextjs/scripts/config/index.ts @@ -0,0 +1,39 @@ +// eslint-disable-next-line @typescript-eslint/no-var-requires +const plugins = require('scripts/temp/config-plugins'); + +/** + * JSS configuration object + */ +export interface JssConfig extends Record { + sitecoreApiKey?: string; + sitecoreApiHost?: string; + jssAppName?: string; + graphQLEndpointPath?: string; + defaultLanguage?: string; + graphQLEndpoint?: string; +} + +export interface ConfigPlugin { + /** + * Detect order when the plugin should be called, e.g. 0 - will be called first (can be a plugin which data is required for other plugins) + */ + order: number; + /** + * A function which will be called during config generation + * @param {JssConfig} config Current (accumulated) config + */ + exec(config: JssConfig): Promise; +} + +export class JssConfigFactory { + public async create(defaultConfig: JssConfig = {}): Promise { + return (Object.values(plugins) as ConfigPlugin[]) + .sort((p1, p2) => p1.order - p2.order) + .reduce( + (promise, plugin) => promise.then((config) => plugin.exec(config)), + Promise.resolve(defaultConfig) + ); + } +} + +export const jssConfigFactory = new JssConfigFactory(); diff --git a/packages/create-sitecore-jss/src/templates/nextjs/scripts/config/plugins/computed.ts b/packages/create-sitecore-jss/src/templates/nextjs/scripts/config/plugins/computed.ts new file mode 100644 index 0000000000..132f026eae --- /dev/null +++ b/packages/create-sitecore-jss/src/templates/nextjs/scripts/config/plugins/computed.ts @@ -0,0 +1,15 @@ +import { ConfigPlugin, JssConfig } from '..'; + +class ComputedPlugin implements ConfigPlugin { + order = 3; + + async exec(config: JssConfig) { + return Object.assign({}, config, { + // The GraphQL endpoint is an example of making a _computed_ config setting + // based on other config settings. + graphQLEndpoint: `${config.sitecoreApiHost}${config.graphQLEndpointPath}`, + }); + } +} + +export const computedPlugin = new ComputedPlugin(); diff --git a/packages/create-sitecore-jss/src/templates/nextjs/scripts/config/plugins/package-json.ts b/packages/create-sitecore-jss/src/templates/nextjs/scripts/config/plugins/package-json.ts new file mode 100644 index 0000000000..6263a0e176 --- /dev/null +++ b/packages/create-sitecore-jss/src/templates/nextjs/scripts/config/plugins/package-json.ts @@ -0,0 +1,18 @@ +import { ConfigPlugin, JssConfig } from '..'; +import packageConfig from 'package.json'; + +class PackageJsonPlugin implements ConfigPlugin { + order = 2; + + async exec(config: JssConfig) { + if (!packageConfig.config) return config; + + return Object.assign({}, config, { + jssAppName: packageConfig.config.appName, + graphQLEndpointPath: packageConfig.config.graphQLEndpointPath, + defaultLanguage: packageConfig.config.language || 'en', + }); + } +} + +export const packageJsonPlugin = new PackageJsonPlugin(); diff --git a/packages/create-sitecore-jss/src/templates/nextjs/scripts/config/plugins/scjssconfig.ts b/packages/create-sitecore-jss/src/templates/nextjs/scripts/config/plugins/scjssconfig.ts new file mode 100644 index 0000000000..3ec98bc55b --- /dev/null +++ b/packages/create-sitecore-jss/src/templates/nextjs/scripts/config/plugins/scjssconfig.ts @@ -0,0 +1,25 @@ +import { ConfigPlugin, JssConfig } from '..'; + +class ScJssConfigPlugin implements ConfigPlugin { + order = 1; + + async exec(config: JssConfig) { + // scjssconfig.json may not exist if you've never run `jss setup` (development) + // or are depending on environment variables instead (production). + let scJssConfig; + try { + scJssConfig = require('scjssconfig.json'); + } catch (e) { + return config; + } + + if (!scJssConfig) return config; + + return Object.assign({}, config, { + sitecoreApiKey: scJssConfig.sitecore?.apiKey, + sitecoreApiHost: scJssConfig.sitecore?.layoutServiceHost, + }); + } +} + +export const scjssconfigPlugin = new ScJssConfigPlugin(); diff --git a/packages/create-sitecore-jss/src/templates/nextjs/scripts/generate-config.ts b/packages/create-sitecore-jss/src/templates/nextjs/scripts/generate-config.ts index 30ec5ea4ba..71b0a91c9f 100644 --- a/packages/create-sitecore-jss/src/templates/nextjs/scripts/generate-config.ts +++ b/packages/create-sitecore-jss/src/templates/nextjs/scripts/generate-config.ts @@ -1,53 +1,53 @@ import fs from 'fs'; import path from 'path'; import { constantCase } from 'constant-case'; -import packageConfig from '../package.json'; +import { JssConfig, jssConfigFactory } from './config'; -/* eslint-disable no-console */ +/* + CONFIG GENERATION + Generates the /src/temp/config.js file which contains runtime configuration + that the app can import and use. +*/ -/** - * Generate config - * The object returned from this function will be made available by importing src/temp/config.js. - * This is executed prior to the build running, so it's a way to inject environment or build config-specific - * settings as variables into the JSS app. - * NOTE! Any configs returned here will be written into the client-side JS bundle. DO NOT PUT SECRETS HERE. - * @param {object} configOverrides Keys in this object will override any equivalent global config keys. - */ -export function generateConfig(configOverrides?: { [key: string]: string }): void { - const defaultConfig = { - sitecoreApiKey: 'no-api-key-set', - sitecoreApiHost: '', - jssAppName: 'Unknown', - }; +const defaultConfig: JssConfig = { + sitecoreApiKey: 'no-api-key-set', + sitecoreApiHost: '', + jssAppName: 'Unknown', +}; - // require + combine config sources - const scjssConfig = transformScJssConfig(); - const packageJson = transformPackageConfig(); +generateConfig(defaultConfig); - // Object.assign merges the objects in order, so config overrides are performed as: - // default config <-- scjssconfig.json <-- package.json <-- configOverrides - // Optional: add any other dynamic config source (e.g. environment-specific config files). - const config = Object.assign(defaultConfig, scjssConfig, packageJson, configOverrides); - - // The GraphQL endpoint is an example of making a _computed_ config setting - // based on other config settings. - const computedConfig: { [key: string]: string } = {}; - computedConfig.graphQLEndpoint = '`${config.sitecoreApiHost}${config.graphQLEndpointPath}`'; +/** + * Generates the JSS config based on config plugins (under ./config/plugins) + * and then write the config to disk. + * @param {JssConfig} defaultConfig Default configuration. + */ +function generateConfig(defaultConfig: JssConfig): void { + jssConfigFactory + .create(defaultConfig) + .then((config) => { + writeConfig(config); + }) + .catch((e) => { + console.error('Error generating config'); + console.error(e); + process.exit(1); + }); +} +/** + * Writes the config object to disk with support for environment variables. + * @param {JssConfig} config JSS configuration to write. + */ +function writeConfig(config: JssConfig): void { let configText = `/* eslint-disable */ // Do not edit this file, it is auto-generated at build time! // See scripts/bootstrap.ts to modify the generation of this file. const config = {};\n`; - // Set base configuration values, allowing override with environment variables + // Set configuration values, allowing override with environment variables Object.keys(config).forEach((prop) => { - configText += `config.${prop} = process.env.${constantCase(prop)} || "${config[prop]}",\n`; - }); - // Set computed values, allowing override with environment variables - Object.keys(computedConfig).forEach((prop) => { - configText += `config.${prop} = process.env.${constantCase(prop)} || ${ - computedConfig[prop] - };\n`; + configText += `config.${prop} = process.env.${constantCase(prop)} || '${config[prop]}',\n`; }); configText += `module.exports = config;`; @@ -55,32 +55,3 @@ const config = {};\n`; console.log(`Writing runtime config to ${configPath}`); fs.writeFileSync(configPath, configText, { encoding: 'utf8' }); } - -function transformScJssConfig() { - // scjssconfig.json may not exist if you've never run `jss setup` (development) - // or are depending on environment variables instead (production). - let config; - try { - // eslint-disable-next-line global-require - config = require('../scjssconfig.json'); - } catch (e) { - return {}; - } - - if (!config) return {}; - - return { - sitecoreApiKey: config.sitecore.apiKey, - sitecoreApiHost: config.sitecore.layoutServiceHost, - }; -} - -function transformPackageConfig() { - if (!packageConfig.config) return {}; - - return { - jssAppName: packageConfig.config.appName, - graphQLEndpointPath: packageConfig.config.graphQLEndpointPath, - defaultLanguage: packageConfig.config.language || 'en', - }; -} diff --git a/packages/create-sitecore-jss/src/templates/nextjs/scripts/generate-plugins.ts b/packages/create-sitecore-jss/src/templates/nextjs/scripts/generate-plugins.ts index 4fa646dc86..1cb537bf1d 100644 --- a/packages/create-sitecore-jss/src/templates/nextjs/scripts/generate-plugins.ts +++ b/packages/create-sitecore-jss/src/templates/nextjs/scripts/generate-plugins.ts @@ -31,6 +31,11 @@ interface PluginFile { } const pluginDefinitions = [ + { + listPath: 'src/temp/config-plugins.ts', + rootPath: 'scripts/config/plugins', + moduleType: ModuleType.ESM, + }, { listPath: 'src/temp/sitemap-fetcher-plugins.ts', rootPath: 'src/lib/sitemap-fetcher/plugins', @@ -70,7 +75,8 @@ function run(definitions: PluginDefinition[]) { * Modify this function to use a different convention. */ function writePlugins(listPath: string, rootPath: string, moduleType: ModuleType) { - const pluginName = rootPath.split('/')[2]; + const segments = rootPath.split('/'); + const pluginName = segments[segments.length - 2]; const plugins = getPluginList(rootPath, pluginName); let fileContent = ''; diff --git a/packages/create-sitecore-jss/src/templates/nextjs/scripts/temp/.gitignore b/packages/create-sitecore-jss/src/templates/nextjs/scripts/temp/.gitignore new file mode 100644 index 0000000000..d6b7ef32c8 --- /dev/null +++ b/packages/create-sitecore-jss/src/templates/nextjs/scripts/temp/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/packages/create-sitecore-jss/src/templates/nextjs/tsconfig.scripts.json b/packages/create-sitecore-jss/src/templates/nextjs/tsconfig.scripts.json index 95d91de5d6..e00a2d17c4 100644 --- a/packages/create-sitecore-jss/src/templates/nextjs/tsconfig.scripts.json +++ b/packages/create-sitecore-jss/src/templates/nextjs/tsconfig.scripts.json @@ -1,5 +1,10 @@ { "extends": "./tsconfig.json", + "ts-node": { + "require": [ + "tsconfig-paths/register" + ] + }, "compilerOptions": { "module": "commonjs" } diff --git a/packages/sitecore-jss-nextjs/src/index.ts b/packages/sitecore-jss-nextjs/src/index.ts index c027bfb619..e2da79a6b8 100644 --- a/packages/sitecore-jss-nextjs/src/index.ts +++ b/packages/sitecore-jss-nextjs/src/index.ts @@ -90,6 +90,9 @@ export { GraphQLErrorPagesService, GraphQLErrorPagesServiceConfig, ErrorPages, + SiteInfo, + GraphQLSiteInfoService, + GraphQLSiteInfoServiceConfig, } from '@sitecore-jss/sitecore-jss/site'; export { StaticPath } from './services/graphql-sitemap-service'; diff --git a/packages/sitecore-jss/src/site/graphql-siteinfo-service.ts b/packages/sitecore-jss/src/site/graphql-siteinfo-service.ts index 80a4b82613..a46567c2ad 100644 --- a/packages/sitecore-jss/src/site/graphql-siteinfo-service.ts +++ b/packages/sitecore-jss/src/site/graphql-siteinfo-service.ts @@ -14,9 +14,6 @@ const defaultQuery = /* GraphQL */ ` hostName: field(name: "Hostname") { value } - virtualFolder: field(name: "VirtualFolder") { - value - } language: field(name: "Language") { value } @@ -27,9 +24,17 @@ const defaultQuery = /* GraphQL */ ` `; export type SiteInfo = { + /** + * Site name + */ name: string; + /** + * Site host name. May include multiple values (separated by '|') and wildcards ('*') + */ hostName: string; - virtualFolder: string; + /** + * Site default language + */ language: string; }; @@ -55,9 +60,6 @@ type GraphQLSiteInfoResult = { hostName: { value: string; }; - virtualFolder: { - value: string; - }; language: { value: string; }; @@ -91,7 +93,6 @@ export class GraphQLSiteInfoService { result.push({ name: current.name, hostName: current.hostName.value, - virtualFolder: current.virtualFolder.value, language: current.language.value, }); return result; From d0c67812a840fd24cbcb4ea9c70f5616e4c38795 Mon Sep 17 00:00:00 2001 From: Adam Brauer <400763+ambrauer@users.noreply.github.com> Date: Tue, 3 Jan 2023 08:44:44 -0600 Subject: [PATCH 4/7] Standardized comments in config plugins. Misc fixes. --- .../nextjs-multisite/scripts/config/plugins/multisite.ts | 2 +- .../scripts/config/plugins/disconnected.ts | 6 +++++- .../templates/nextjs/scripts/config/plugins/computed.ts | 7 +++++-- .../nextjs/scripts/config/plugins/package-json.ts | 3 +++ .../templates/nextjs/scripts/config/plugins/scjssconfig.ts | 7 +++++-- .../src/templates/nextjs/scripts/generate-config.ts | 2 +- .../src/templates/nextjs/scripts/generate-plugins.ts | 2 +- 7 files changed, 21 insertions(+), 8 deletions(-) diff --git a/packages/create-sitecore-jss/src/templates/nextjs-multisite/scripts/config/plugins/multisite.ts b/packages/create-sitecore-jss/src/templates/nextjs-multisite/scripts/config/plugins/multisite.ts index 152976865f..01866c4282 100644 --- a/packages/create-sitecore-jss/src/templates/nextjs-multisite/scripts/config/plugins/multisite.ts +++ b/packages/create-sitecore-jss/src/templates/nextjs-multisite/scripts/config/plugins/multisite.ts @@ -1,6 +1,6 @@ import 'dotenv/config'; import chalk from 'chalk'; -import { ConfigPlugin, JssConfig } from '../../../../nextjs/scripts/config'; +import { ConfigPlugin, JssConfig } from '..'; import { GraphQLSiteInfoService, SiteInfo } from '@sitecore-jss/sitecore-jss-nextjs'; /** diff --git a/packages/create-sitecore-jss/src/templates/nextjs-styleguide/scripts/config/plugins/disconnected.ts b/packages/create-sitecore-jss/src/templates/nextjs-styleguide/scripts/config/plugins/disconnected.ts index 71e8f76358..36571f2cdd 100644 --- a/packages/create-sitecore-jss/src/templates/nextjs-styleguide/scripts/config/plugins/disconnected.ts +++ b/packages/create-sitecore-jss/src/templates/nextjs-styleguide/scripts/config/plugins/disconnected.ts @@ -1,8 +1,12 @@ import 'dotenv/config'; import chalk from 'chalk'; import { constants } from '@sitecore-jss/sitecore-jss-nextjs'; -import { ConfigPlugin, JssConfig } from '../../../../nextjs/scripts/config'; +import { ConfigPlugin, JssConfig } from '..'; +/** + * This plugin will override the "sitecoreApiHost" config prop + * for disconnected mode (using disconnected server). + */ class DisconnectedPlugin implements ConfigPlugin { order = 4; diff --git a/packages/create-sitecore-jss/src/templates/nextjs/scripts/config/plugins/computed.ts b/packages/create-sitecore-jss/src/templates/nextjs/scripts/config/plugins/computed.ts index 132f026eae..3cc3d9c990 100644 --- a/packages/create-sitecore-jss/src/templates/nextjs/scripts/config/plugins/computed.ts +++ b/packages/create-sitecore-jss/src/templates/nextjs/scripts/config/plugins/computed.ts @@ -1,12 +1,15 @@ import { ConfigPlugin, JssConfig } from '..'; +/** + * This plugin will set computed config props. + * The "graphQLEndpoint" is an example of making a _computed_ config setting + * based on other config settings. + */ class ComputedPlugin implements ConfigPlugin { order = 3; async exec(config: JssConfig) { return Object.assign({}, config, { - // The GraphQL endpoint is an example of making a _computed_ config setting - // based on other config settings. graphQLEndpoint: `${config.sitecoreApiHost}${config.graphQLEndpointPath}`, }); } diff --git a/packages/create-sitecore-jss/src/templates/nextjs/scripts/config/plugins/package-json.ts b/packages/create-sitecore-jss/src/templates/nextjs/scripts/config/plugins/package-json.ts index 6263a0e176..67d6f45b6a 100644 --- a/packages/create-sitecore-jss/src/templates/nextjs/scripts/config/plugins/package-json.ts +++ b/packages/create-sitecore-jss/src/templates/nextjs/scripts/config/plugins/package-json.ts @@ -1,6 +1,9 @@ import { ConfigPlugin, JssConfig } from '..'; import packageConfig from 'package.json'; +/** + * This plugin will set config props based on package.json. + */ class PackageJsonPlugin implements ConfigPlugin { order = 2; diff --git a/packages/create-sitecore-jss/src/templates/nextjs/scripts/config/plugins/scjssconfig.ts b/packages/create-sitecore-jss/src/templates/nextjs/scripts/config/plugins/scjssconfig.ts index 3ec98bc55b..4967161658 100644 --- a/packages/create-sitecore-jss/src/templates/nextjs/scripts/config/plugins/scjssconfig.ts +++ b/packages/create-sitecore-jss/src/templates/nextjs/scripts/config/plugins/scjssconfig.ts @@ -1,11 +1,14 @@ import { ConfigPlugin, JssConfig } from '..'; +/** + * This plugin will set config props based on scjssconfig.json. + * scjssconfig.json may not exist if you've never run `jss setup` (development) + * or are depending on environment variables instead (production). + */ class ScJssConfigPlugin implements ConfigPlugin { order = 1; async exec(config: JssConfig) { - // scjssconfig.json may not exist if you've never run `jss setup` (development) - // or are depending on environment variables instead (production). let scJssConfig; try { scJssConfig = require('scjssconfig.json'); diff --git a/packages/create-sitecore-jss/src/templates/nextjs/scripts/generate-config.ts b/packages/create-sitecore-jss/src/templates/nextjs/scripts/generate-config.ts index 71b0a91c9f..9ca0b0f4ac 100644 --- a/packages/create-sitecore-jss/src/templates/nextjs/scripts/generate-config.ts +++ b/packages/create-sitecore-jss/src/templates/nextjs/scripts/generate-config.ts @@ -19,7 +19,7 @@ generateConfig(defaultConfig); /** * Generates the JSS config based on config plugins (under ./config/plugins) - * and then write the config to disk. + * and then writes the config to disk. * @param {JssConfig} defaultConfig Default configuration. */ function generateConfig(defaultConfig: JssConfig): void { diff --git a/packages/create-sitecore-jss/src/templates/nextjs/scripts/generate-plugins.ts b/packages/create-sitecore-jss/src/templates/nextjs/scripts/generate-plugins.ts index 1cb537bf1d..ca399d0435 100644 --- a/packages/create-sitecore-jss/src/templates/nextjs/scripts/generate-plugins.ts +++ b/packages/create-sitecore-jss/src/templates/nextjs/scripts/generate-plugins.ts @@ -32,7 +32,7 @@ interface PluginFile { const pluginDefinitions = [ { - listPath: 'src/temp/config-plugins.ts', + listPath: 'scripts/temp/config-plugins.ts', rootPath: 'scripts/config/plugins', moduleType: ModuleType.ESM, }, From 79dbbe38b8fa69ddd227df4159ba88bc13f1628f Mon Sep 17 00:00:00 2001 From: Adam Brauer <400763+ambrauer@users.noreply.github.com> Date: Tue, 3 Jan 2023 09:58:43 -0600 Subject: [PATCH 5/7] Fixed tests and relocated headlessSiteGroupingTemplate constant (since this query is temp anyway) --- packages/sitecore-jss/src/constants.ts | 2 -- .../src/site/graphql-siteinfo-service.test.ts | 10 ---------- .../sitecore-jss/src/site/graphql-siteinfo-service.ts | 3 ++- 3 files changed, 2 insertions(+), 13 deletions(-) diff --git a/packages/sitecore-jss/src/constants.ts b/packages/sitecore-jss/src/constants.ts index 0e4f0d10e0..fee6b3dde8 100644 --- a/packages/sitecore-jss/src/constants.ts +++ b/packages/sitecore-jss/src/constants.ts @@ -16,6 +16,4 @@ export const JSS_MODE = { DISCONNECTED: 'disconnected', }; -export const headlessSiteGroupingTemplate = 'E46F3AF2-39FA-4866-A157-7017C4B2A40C'; - export const siteNameError = 'The siteName cannot be empty'; diff --git a/packages/sitecore-jss/src/site/graphql-siteinfo-service.test.ts b/packages/sitecore-jss/src/site/graphql-siteinfo-service.test.ts index 3c842bb0b8..69ccb09b83 100644 --- a/packages/sitecore-jss/src/site/graphql-siteinfo-service.test.ts +++ b/packages/sitecore-jss/src/site/graphql-siteinfo-service.test.ts @@ -14,9 +14,6 @@ describe('GraphQLSiteInfoService', () => { hostName: { value: 'restricted.gov', }, - virtualFolder: { - value: '/aliens', - }, language: { value: 'en', }, @@ -26,9 +23,6 @@ describe('GraphQLSiteInfoService', () => { hostName: { value: 'pr.showercurtains.org', }, - virtualFolder: { - value: '/we-are-open', - }, language: { value: '', }, @@ -63,13 +57,11 @@ describe('GraphQLSiteInfoService', () => { { name: 'site 51', hostName: 'restricted.gov', - virtualFolder: '/aliens', language: 'en', }, { name: 'public', hostName: 'pr.showercurtains.org', - virtualFolder: '/we-are-open', language: '', }, ]); @@ -108,13 +100,11 @@ describe('GraphQLSiteInfoService', () => { { name: 'site 51', hostName: 'restricted.gov', - virtualFolder: '/aliens', language: 'en', }, { name: 'public', hostName: 'pr.showercurtains.org', - virtualFolder: '/we-are-open', language: '', }, ]); diff --git a/packages/sitecore-jss/src/site/graphql-siteinfo-service.ts b/packages/sitecore-jss/src/site/graphql-siteinfo-service.ts index a46567c2ad..bc10133030 100644 --- a/packages/sitecore-jss/src/site/graphql-siteinfo-service.ts +++ b/packages/sitecore-jss/src/site/graphql-siteinfo-service.ts @@ -1,7 +1,8 @@ import { GraphQLClient, GraphQLRequestClient } from '../graphql'; import debug from '../debug'; import { CacheClient, CacheOptions, MemoryCacheClient } from '../cache-client'; -import { headlessSiteGroupingTemplate } from '../constants'; + +const headlessSiteGroupingTemplate = 'E46F3AF2-39FA-4866-A157-7017C4B2A40C'; const defaultQuery = /* GraphQL */ ` { From ce9bf219ad77658ba082fc253daecd4e889d718f Mon Sep 17 00:00:00 2001 From: Adam Brauer <400763+ambrauer@users.noreply.github.com> Date: Tue, 3 Jan 2023 10:28:19 -0600 Subject: [PATCH 6/7] Moved defaultLanguage of 'en' to defaultConfig --- .../src/templates/nextjs/scripts/config/plugins/package-json.ts | 2 +- .../src/templates/nextjs/scripts/generate-config.ts | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/create-sitecore-jss/src/templates/nextjs/scripts/config/plugins/package-json.ts b/packages/create-sitecore-jss/src/templates/nextjs/scripts/config/plugins/package-json.ts index 67d6f45b6a..f1b28a5225 100644 --- a/packages/create-sitecore-jss/src/templates/nextjs/scripts/config/plugins/package-json.ts +++ b/packages/create-sitecore-jss/src/templates/nextjs/scripts/config/plugins/package-json.ts @@ -13,7 +13,7 @@ class PackageJsonPlugin implements ConfigPlugin { return Object.assign({}, config, { jssAppName: packageConfig.config.appName, graphQLEndpointPath: packageConfig.config.graphQLEndpointPath, - defaultLanguage: packageConfig.config.language || 'en', + defaultLanguage: packageConfig.config.language, }); } } diff --git a/packages/create-sitecore-jss/src/templates/nextjs/scripts/generate-config.ts b/packages/create-sitecore-jss/src/templates/nextjs/scripts/generate-config.ts index 9ca0b0f4ac..db3a565686 100644 --- a/packages/create-sitecore-jss/src/templates/nextjs/scripts/generate-config.ts +++ b/packages/create-sitecore-jss/src/templates/nextjs/scripts/generate-config.ts @@ -13,6 +13,8 @@ const defaultConfig: JssConfig = { sitecoreApiKey: 'no-api-key-set', sitecoreApiHost: '', jssAppName: 'Unknown', + graphQLEndpointPath: '', + defaultLanguage: 'en', }; generateConfig(defaultConfig); From 7b93bf4bf821756c4b3875f6a47ffa8750663aa7 Mon Sep 17 00:00:00 2001 From: Adam Brauer <400763+ambrauer@users.noreply.github.com> Date: Tue, 3 Jan 2023 10:35:19 -0600 Subject: [PATCH 7/7] Simplify config plugin order. Delete multisite-sample.ts --- .../src/templates/nextjs-multisite/multisite-sample.ts | 1 - .../nextjs-multisite/scripts/config/plugins/multisite.ts | 2 +- .../nextjs-styleguide/scripts/config/plugins/disconnected.ts | 2 +- .../src/templates/nextjs/scripts/config/plugins/computed.ts | 2 +- .../src/templates/nextjs/scripts/config/plugins/package-json.ts | 2 +- 5 files changed, 4 insertions(+), 5 deletions(-) delete mode 100644 packages/create-sitecore-jss/src/templates/nextjs-multisite/multisite-sample.ts diff --git a/packages/create-sitecore-jss/src/templates/nextjs-multisite/multisite-sample.ts b/packages/create-sitecore-jss/src/templates/nextjs-multisite/multisite-sample.ts deleted file mode 100644 index e02abfc9b0..0000000000 --- a/packages/create-sitecore-jss/src/templates/nextjs-multisite/multisite-sample.ts +++ /dev/null @@ -1 +0,0 @@ - diff --git a/packages/create-sitecore-jss/src/templates/nextjs-multisite/scripts/config/plugins/multisite.ts b/packages/create-sitecore-jss/src/templates/nextjs-multisite/scripts/config/plugins/multisite.ts index 01866c4282..c9baf1bcf7 100644 --- a/packages/create-sitecore-jss/src/templates/nextjs-multisite/scripts/config/plugins/multisite.ts +++ b/packages/create-sitecore-jss/src/templates/nextjs-multisite/scripts/config/plugins/multisite.ts @@ -9,7 +9,7 @@ import { GraphQLSiteInfoService, SiteInfo } from '@sitecore-jss/sitecore-jss-nex * You could easily modify this to fetch from another source such as a static JSON file instead. */ class MultisitePlugin implements ConfigPlugin { - order = 4; + order = 3; async exec(config: JssConfig) { let sites: SiteInfo[] = []; diff --git a/packages/create-sitecore-jss/src/templates/nextjs-styleguide/scripts/config/plugins/disconnected.ts b/packages/create-sitecore-jss/src/templates/nextjs-styleguide/scripts/config/plugins/disconnected.ts index 36571f2cdd..bd5c185d59 100644 --- a/packages/create-sitecore-jss/src/templates/nextjs-styleguide/scripts/config/plugins/disconnected.ts +++ b/packages/create-sitecore-jss/src/templates/nextjs-styleguide/scripts/config/plugins/disconnected.ts @@ -8,7 +8,7 @@ import { ConfigPlugin, JssConfig } from '..'; * for disconnected mode (using disconnected server). */ class DisconnectedPlugin implements ConfigPlugin { - order = 4; + order = 3; async exec(config: JssConfig) { const disconnected = process.env.JSS_MODE === constants.JSS_MODE.DISCONNECTED; diff --git a/packages/create-sitecore-jss/src/templates/nextjs/scripts/config/plugins/computed.ts b/packages/create-sitecore-jss/src/templates/nextjs/scripts/config/plugins/computed.ts index 3cc3d9c990..dc487ce88b 100644 --- a/packages/create-sitecore-jss/src/templates/nextjs/scripts/config/plugins/computed.ts +++ b/packages/create-sitecore-jss/src/templates/nextjs/scripts/config/plugins/computed.ts @@ -6,7 +6,7 @@ import { ConfigPlugin, JssConfig } from '..'; * based on other config settings. */ class ComputedPlugin implements ConfigPlugin { - order = 3; + order = 2; async exec(config: JssConfig) { return Object.assign({}, config, { diff --git a/packages/create-sitecore-jss/src/templates/nextjs/scripts/config/plugins/package-json.ts b/packages/create-sitecore-jss/src/templates/nextjs/scripts/config/plugins/package-json.ts index f1b28a5225..3fffb6b1ec 100644 --- a/packages/create-sitecore-jss/src/templates/nextjs/scripts/config/plugins/package-json.ts +++ b/packages/create-sitecore-jss/src/templates/nextjs/scripts/config/plugins/package-json.ts @@ -5,7 +5,7 @@ import packageConfig from 'package.json'; * This plugin will set config props based on package.json. */ class PackageJsonPlugin implements ConfigPlugin { - order = 2; + order = 1; async exec(config: JssConfig) { if (!packageConfig.config) return config;