Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[templates] Introduce layout service REST configuration name environment variable #1543

Merged
merged 12 commits into from
Jul 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ Our versioning strategy is as follows:

### 🎉 New Features & Improvements

* `[templates/nextjs]` `[templates/react]` `[templates/vue]` `[templates/angular]` Introduce layout service REST configuration name environment variable ([#1543](https://github.com/Sitecore/jss/pull/1543))
* `[templates/nextjs]` `[sitecore-jss-nextjs]` Support for out-of-process editing data caches was added. Vercel KV or a custom Redis cache can be used to improve editing in Pages and Experience Editor when using Vercel deployment as editing/rendering host ([#1530](https://github.com/Sitecore/jss/pull/1530))

### 🐛 Bug Fixes
Expand Down
186 changes: 128 additions & 58 deletions packages/create-sitecore-jss/src/common/processes/transform.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import * as helpers from '../utils/helpers';
const {
transformFilename,
merge,
concatEnv,
mergeEnv,
diffFiles,
diffAndWriteFiles,
transform: transformFunc,
Expand Down Expand Up @@ -86,65 +86,135 @@ describe('transform', () => {
});
});

describe('concatEnv', () => {
it('should combine content', () => {
const target = `VAL1=ONE
VAL2=TWO`;
const source = `VAL3=three
# Comment
VAL4=four`;

const result = concatEnv(target, source);

expect(result).to.contain(`VAL1=ONE
VAL2=TWO`);
expect(result).to.contain(`VAL3=three
# Comment
VAL4=four`);
describe('mergeEnv', () => {
it('should merge content when source includes duplicates and unique variables', () => {
const target = [
'# Foo1',
'# Foo2',
'VAL1=ONE',
'VAL2=TWO',
'',
'',
'# Bar1',
'# Bar2',
'VAL3=three',
].join('\r\n');
const source = [
'VAL4=four',
'# Foo1',
'# Foo2',
'VAL1=ONE_MODIFIED',
'# Bar5',
'VAL5=five',
'',
'# Car1',
'# Car2',
'VAL3=THREE_MODIFIED',
'',
'',
'',
'# Bar6',
'VAL6=SIX',
].join('\r\n');

const result = mergeEnv(target, source);

expect(result).to.equal(
[
'# Foo1',
'# Foo2',
'VAL1=ONE_MODIFIED',
'VAL2=TWO',
'',
'',
'# Bar1',
'# Bar2',
'VAL3=THREE_MODIFIED',
'VAL4=four',
'# Bar5',
'VAL5=five',
'',
'# Bar6',
'VAL6=SIX',
].join('\r\n')
);
});

it('should join with crlf', () => {
const target = 'foo';
const source = 'bar';

const result = concatEnv(target, source);

expect(result).to.equal('foo\r\nbar');
it('should merge content when source includes duplicates only', () => {
const target = [
'# Foo1',
'# Foo2',
'VAL1=ONE',
'VAL2=TWO',
'# Bar1',
'# Bar2',
'VAL3=three',
].join('\r\n');
const source = ['# Bar1', '# Bar2', 'VAL3=three_modified', 'VAL2=two_modified'].join('\r\n');

const result = mergeEnv(target, source);

expect(result).to.equal(
[
'# Foo1',
'# Foo2',
'VAL1=ONE',
'VAL2=two_modified',
'# Bar1',
'# Bar2',
'VAL3=three_modified',
].join('\r\n')
);
});

it('should not add if all values exist', () => {
const target = `VAL1=ONE
VAL2=TWO
VAL3=three
VAL4=four`;
const source = `VAL3=three
# Comment
VAL4=four`;

const result = concatEnv(target, source);

expect(result).to.contain(`VAL1=ONE
VAL2=TWO`);
expect(result).to.not.contain(`VAL3=three
# Comment
VAL4=four`);
it('should merge content when source includes unique values only', () => {
const target = [
'# Foo1',
'# Foo2',
'VAL1=ONE',
'VAL2=TWO',
'# Bar1',
'# Bar2',
'VAL3=three',
].join('\r\n');
const source = ['# Bar4', '# Bar5', 'VAL4=four', 'VAL5=five'].join('\r\n');

const result = mergeEnv(target, source);

expect(result).to.equal(
[
'# Foo1',
'# Foo2',
'VAL1=ONE',
'VAL2=TWO',
'# Bar1',
'# Bar2',
'VAL3=three',
'# Bar4',
'# Bar5',
'VAL4=four',
'VAL5=five',
].join('\r\n')
);
});

it('should add if some values exist', () => {
const target = `VAL1=ONE
VAL2=TWO
VAL3=three`;
const source = `VAL3=three
# Comment
VAL4=four`;

const result = concatEnv(target, source);

expect(result).to.contain(`VAL1=ONE
VAL2=TWO`);
expect(result).to.contain(`VAL3=three
# Comment
VAL4=four`);
it('should return target content when source is empty', () => {
const target = [
'# Foo1',
'# Foo2',
'VAL1=ONE',
'VAL2=TWO',
'# Bar1',
'# Bar2',
'VAL3=three',
].join('\r\n');
const source = '';

const result = mergeEnv(target, source);

expect(result).to.equal(
['# Foo1', '# Foo2', 'VAL1=ONE', 'VAL2=TWO', '# Bar1', '# Bar2', 'VAL3=three'].join('\r\n')
);
});
});

Expand Down Expand Up @@ -401,7 +471,7 @@ describe('transform', () => {
let fsReadFileSunc: SinonStub;
let globSyncStub: SinonStub;
let ejsRenderFileStub: SinonStub;
let concatEnvStub: SinonStub;
let mergeEnvStub: SinonStub;
let mergeStub: SinonStub;
let diffAndWriteFilesStub: SinonStub;
let writeFileToPathStub: SinonStub;
Expand All @@ -420,7 +490,7 @@ describe('transform', () => {
fsReadFileSunc?.restore();
globSyncStub?.restore();
ejsRenderFileStub?.restore();
concatEnvStub?.restore();
mergeEnvStub?.restore();
mergeStub?.restore();
diffAndWriteFilesStub?.restore();
writeFileToPathStub?.restore();
Expand Down Expand Up @@ -599,7 +669,7 @@ describe('transform', () => {
fsExistsSyncStub = sinon.stub(fs, 'existsSync').returns(true);
fsReadFileSunc = sinon.stub(fs, 'readFileSync').returns(currentDotEnv);
ejsRenderFileStub = sinon.stub(ejs, 'renderFile').returns(Promise.resolve(templateDotEnv));
concatEnvStub = sinon.stub(transform, 'concatEnv').returns(concatDotEnv);
mergeEnvStub = sinon.stub(transform, 'mergeEnv').returns(concatDotEnv);
diffAndWriteFilesStub = sinon.stub(transform, 'diffAndWriteFiles');

const answers = {
Expand All @@ -619,7 +689,7 @@ describe('transform', () => {
getAppPrefix: helpers.getAppPrefix,
},
});
expect(concatEnvStub).to.have.been.calledOnceWith(currentDotEnv, templateDotEnv);
expect(mergeEnvStub).to.have.been.calledOnceWith(currentDotEnv, templateDotEnv);
expect(diffAndWriteFilesStub).to.have.been.calledOnceWith({
rendered: concatDotEnv,
pathToNewFile: path.join(destinationPath, file),
Expand Down
55 changes: 43 additions & 12 deletions packages/create-sitecore-jss/src/common/processes/transform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,16 +61,47 @@ export const merge = (targetObj: JsonObjectType, sourceObj: JsonObjectType): Jso
return mergeObject(targetObj, sourceObj);
};

export const concatEnv = (targetContent: string, sourceContent: string): string => {
const env = parse(sourceContent);
if (
env &&
Object.keys(env).length > 0 &&
Object.keys(env).every((value) => targetContent.includes(value))
) {
// Don't add if the target already contains every .env value
return targetContent;
}
export const mergeEnv = (targetContent: string, sourceContent: string): string => {
const sourceEnv = parse(sourceContent);

if (!sourceEnv || !Object.keys(sourceEnv).length) return targetContent;

const targetEnv = parse(targetContent);

const sourceLines = sourceContent.split('\r\n');

Object.keys(sourceEnv).forEach((sourceEnvVar) => {
const isDuplicate = Object.keys(targetEnv).includes(sourceEnvVar);

if (!isDuplicate) return;

// Overriding value in a target .env file
targetContent = targetContent.replace(
new RegExp(`^${sourceEnvVar}=.*$`, 'gm'),
`${sourceEnvVar}=${sourceEnv[sourceEnvVar]}`
);

// Removing duplicate variable and related comments in a source .env file,
// since source and target will be concatenated
let lineIndex = sourceLines.findIndex((line) => line.startsWith(sourceEnvVar));

// remove empty lines after the definition
while (sourceLines[lineIndex + 1] === '') {
sourceLines.splice(lineIndex + 1, 1);
}

// remove definition and comments
do {
sourceLines.splice(lineIndex, 1);
lineIndex--;
} while (lineIndex >= 0 && sourceLines[lineIndex].startsWith('#'));
});

sourceContent = sourceLines.join('\r\n');

// No variables left in a source
if (!sourceContent) return targetContent;

// NOTE we are enforcing CRLF for the repo in .gitattributes, so match it here
const eol = '\r\n';
return targetContent + eol + sourceContent;
Expand Down Expand Up @@ -262,8 +293,8 @@ export const transform = async (
// read the current .env and the template .env (rendered with ejs)
const currentDotEnv = fs.readFileSync(path.resolve(process.cwd(), pathToNewFile), 'utf8');
const templateDotEnv = await renderFile(path.resolve(pathToTemplate), ejsData);
// concatenate them and set the result to str which will then go through diff
str = concatEnv(currentDotEnv, templateDotEnv);
// merge them and set the result to str which will then go through diff
str = mergeEnv(currentDotEnv, templateDotEnv);
}

str = str ?? (await renderFile(path.resolve(pathToTemplate), ejsData));
Expand Down
66 changes: 33 additions & 33 deletions packages/create-sitecore-jss/src/templates/angular/.env
Original file line number Diff line number Diff line change
@@ -1,33 +1,33 @@
# Your Sitecore API key is needed to build the app. Typically, the API key is
# defined in `scjssconfig.json` (as `sitecore.apiKey`). This file may not exist
# when building locally (if you've never run `jss setup`), or when building in a
# higher environment (since `scjssconfig.json` is ignored from source control).
# In this case, use this environment variable to provide the value at build time.
SITECORE_API_KEY=

# Your Sitecore API hostname is needed to build the app. Typically, the API host is
# defined in `scjssconfig.json` (as `sitecore.layoutServiceHost`). This file may
# not exist when building locally (if you've never run `jss setup`), or when building
# in a higher environment (since `scjssconfig.json` is ignored from source control).
# In this case, use this environment variable to provide the value at build time.
SITECORE_API_HOST=

# Your GraphQL Edge endpoint. This is required for Sitecore Experience Edge.
# For Sitecore XM, this is typically optional. By default, the endpoint is calculated using
# the resolved Sitecore API hostname + the `graphQLEndpointPath` defined in your `package.json`.
GRAPH_QL_ENDPOINT=

# Your default app language.
DEFAULT_LANGUAGE=

# The way in which layout and dictionary data is fetched from Sitecore
FETCH_WITH=<%- fetchWith %>

# Sitecore JSS npm packages utilize the debug module for debug logging.
# https://www.npmjs.com/package/debug
# Set the DEBUG environment variable to 'sitecore-jss:*' to see all logs:
#DEBUG=sitecore-jss:*
# Or be selective and show for example only layout service logs:
#DEBUG=sitecore-jss:layout
# Or everything BUT layout service logs:
#DEBUG=sitecore-jss:*,-sitecore-jss:layout
# Your Sitecore API key is needed to build the app. Typically, the API key is
# defined in `scjssconfig.json` (as `sitecore.apiKey`). This file may not exist
# when building locally (if you've never run `jss setup`), or when building in a
# higher environment (since `scjssconfig.json` is ignored from source control).
# In this case, use this environment variable to provide the value at build time.
SITECORE_API_KEY=
# Your Sitecore API hostname is needed to build the app. Typically, the API host is
# defined in `scjssconfig.json` (as `sitecore.layoutServiceHost`). This file may
# not exist when building locally (if you've never run `jss setup`), or when building
# in a higher environment (since `scjssconfig.json` is ignored from source control).
# In this case, use this environment variable to provide the value at build time.
SITECORE_API_HOST=
# Your GraphQL Edge endpoint. This is required for Sitecore Experience Edge.
# For Sitecore XM, this is typically optional. By default, the endpoint is calculated using
# the resolved Sitecore API hostname + the `graphQLEndpointPath` defined in your `package.json`.
GRAPH_QL_ENDPOINT=
# Your default app language.
DEFAULT_LANGUAGE=
# The way in which layout and dictionary data is fetched from Sitecore
FETCH_WITH=<%- fetchWith %>
# Sitecore JSS npm packages utilize the debug module for debug logging.
# https://www.npmjs.com/package/debug
# Set the DEBUG environment variable to 'sitecore-jss:*' to see all logs:
#DEBUG=sitecore-jss:*
# Or be selective and show for example only layout service logs:
#DEBUG=sitecore-jss:layout
# Or everything BUT layout service logs:
#DEBUG=sitecore-jss:*,-sitecore-jss:layout
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export function generateConfig(configOverrides?: { [key: string]: unknown }, out
sitecoreLayoutServiceConfig: 'jss',
defaultLanguage: 'en',
defaultServerRoute: '/',
layoutServiceConfigurationName: 'default',
};

if (!outputPath) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export class LayoutServiceFactory {
apiHost: environment.sitecoreApiHost,
apiKey: environment.sitecoreApiKey,
siteName: environment.jssAppName,
configurationName: 'default',
configurationName: environment.layoutServiceConfigurationName,
});
}
}
Expand Down
Loading