Skip to content

Commit

Permalink
feat: add new package for managing application config (#1626)
Browse files Browse the repository at this point in the history
* feat: add new package for managing application config

* refactor(config): improve JSON schema

* refactor: further refine JSON schema

* refactor(config): add more text examples

* refactor(config): reimplement schema, add basic utility functions

* refactor(config): remove navbarMenu from schema, implement main build-config function

* refactor(config): use TS, improve schema

* chore(config): command typo

* test(config): for processing config

* chore: ignore build folder

* fix(config): ignore prettier for generated schema.ts

* refactor(config): rename types

* refactor(config): simplify env var interpolation using JSON.parse

* fix: version script to support build and dist folders

* test(config): improve tests setup

* test(config): more validation tests

* refactor(config): attempt to read revision

* chore(config): keep the package private

* docs: improve wording

Co-authored-by: Tobias Deekens <tobias.deekens@commercetools.com>

* refactor(config): rename var

* refactor(config): rename config file to custom-application-config

* test(config): use inline snapshots for better readability

* fix(config): validation order of cloud identifier

* refactor(config): do not use async/await

* refactor: migrate to new application config (#1633)

* refactor: use new application config package to process env and headers

* chore: include application config package in changeset config

* refactor(config): fall back to load deprecated config

* refactor: migrate codebase to use new application config

* refactor: migrate leftovers

* docs: document migration to the new config

* test: fix import

* test(config): for deprecated config files

* fix(vrt): build app for dev mode

* fix(ci): remove unnecessary step

* refactor(config): address feedback

Co-authored-by: Tobias Deekens <tobias.deekens@commercetools.com>
  • Loading branch information
emmenko and tdeekens authored Jul 16, 2020
1 parent cc8b37b commit 728024c
Show file tree
Hide file tree
Showing 81 changed files with 2,176 additions and 551 deletions.
1 change: 1 addition & 0 deletions .changeset/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"@commercetools-backend/loggers",
"@commercetools-frontend/actions-global",
"@commercetools-frontend/application-components",
"@commercetools-frontend/application-config",
"@commercetools-frontend/application-shell",
"@commercetools-frontend/application-shell-connectors",
"@commercetools-frontend/assets",
Expand Down
120 changes: 120 additions & 0 deletions .changeset/wet-insects-push.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
---
'merchant-center-application-template-starter': minor
'@commercetools-frontend/application-config': minor
'@commercetools-frontend/application-shell': minor
'@commercetools-frontend/mc-html-template': minor
'@commercetools-frontend/mc-http-server': minor
'@commercetools-frontend/mc-scripts': minor
'playground': minor
'@commercetools-local/visual-testing-app': minor
---

This release introduces the usage of a new configuration file format and marks the deprecation of the `env.json` and `headers.json` files.

> The `env.json` and `headers.json` files will still keep working but they will be removed in the next major release.
The new configuration format aims to drastically simplify how to configure the Custom Application, as well as to make the configuration process less error prone.
In fact, the new configuration file is backed by a JSON schema that is shipped together with the new package. The configuration file is then validated against the JSON schema.

Furthermore, the new configuration file tries to infer as many required information as possible.

**Migrate to the new configuration file**

The new configuration file is a JSON file with one of the following names:

- `.custom-application-configrc`
- `.custom-application-config.json`
- `custom-application-config.json`

The file is automatically loaded by the other packages, so you don't need to explicitly specify it in, for example, the `mc-scripts` commands.

> The file needs to be located in the project root folder.
For example, given the following `env.json` and `headers.json` files:

```json
{
"applicationName": "Avengers app",
"frontendHost": "localhost:3001",
"mcApiUrl": "https://mc-api.europe-west1.gcp.commercetools.com",
"location": "gcp-eu",
"env": "development",
"cdnUrl": "http://localhost:3001",
"servedByProxy": false
}
```

```json
{
"csp": {
"script-src": [],
"connect-src": ["mc-api.europe-west1.gcp.commercetools.com"],
"style-src": []
}
}
```

and for production mode `env.prod.json` and `headers.prod.json`:

```json
{
"applicationName": "Avengers app",
"frontendHost": "avengers.app",
"mcApiUrl": "https://mc-api.europe-west1.gcp.commercetools.com",
"location": "gcp-eu",
"env": "production",
"cdnUrl": "https://cdn.avengers.app",
"servedByProxy": true
}
```

```json
{
"csp": {
"script-src": ["avengers.app", "cdn.avengers.app"],
"connect-src": [
"mc-api.europe-west1.gcp.commercetools.com",
"avengers.app",
"cdn.avengers.app"
],
"style-src": ["avengers.app", "cdn.avengers.app"]
}
}
```

To migrate them to the new format, add a `custom-application-config.json` (or one of the other file names) with the following content:

```json
{
"name": "Avengers app",
"entryPointUriPath": "avengers",
"cloudIdentifier": "gcp-eu",
"env": {
"production": {
"url": "https://avengers.app",
"cdnUrl": "https://cdn.avengers.app"
}
}
}
```

That's it! All other values are inferred from the config, like CSP headers, etc.

> Note that the environment placeholder values `${env:VALUE}` are still working.
**JSON Schema support for VSCode**

In the VSCode settings (either user settings or workspace settings), reference the schema JSON as described below:

```json
"json.schemas": [
{
"fileMatch": [
"/.custom-application-configrc",
"/.custom-application-config.json",
"/custom-application-config.json"
],
"url": "https://unpkg.com/@commercetools-frontend/application-config/schema.json"
}
]
```
4 changes: 0 additions & 4 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -100,10 +100,6 @@ jobs:
CYPRESS_LOGIN_PASSWORD: ${{ secrets.CYPRESS_LOGIN_PASSWORD }}
CYPRESS_PROJECT_KEY: ${{ secrets. CYPRESS_PROJECT_KEY }}

- name: Preparing Starter template application environment
run: cp .env.template .env
working-directory: application-templates/starter

- name: Building Starter template application
run: yarn template-starter:build

Expand Down
1 change: 1 addition & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ packages/i18n/*.json
packages/application-shell/test-utils/index.js
packages/application-shell-connectors/test-utils/index.js
packages/application-sdk/test-utils/index.js
packages/application-config/src/schema.ts
**/types/generated/
.percy.yml
.cache
Expand Down
17 changes: 17 additions & 0 deletions @types/commercetools-uikit__notifications/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
declare module '@commercetools-uikit/notifications' {
import * as React from 'react';
import { MessageDescriptor } from 'react-intl';

export const version: string;

// <ContentNotification>
export type ContentNotificationProps = {
type: 'success' | 'info' | 'warning' | 'error';
children?: React.ReactNode;
intlMessage?: MessageDescriptor;
};
export const ContentNotification: {
(props: ContentNotificationProps): JSX.Element;
displayName: string;
};
}
3 changes: 0 additions & 3 deletions application-templates/starter/.env.template

This file was deleted.

12 changes: 7 additions & 5 deletions application-templates/starter/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,9 @@ $ create-mc-app my-new-custom-application-project --template starter
$ npx @commercetools-frontend/create-mc-app my-new-custom-application-project --template starter
```

## Adjust the configuration
## Adjust the cloud identifier

Rename the file `.env.template` to `.env`. It contains some environment variables used in the `env.json` and `headers.json` file.

By default the GCP EU environment is configured. If you plan to run the Custom Application in another environment, change the hostname accordingly.
The `custom-application-config.json` is configured to use the HTTP APIs in the GCP-EU region. If you plan to run the Custom Application in another environment, change the cloud identifier accordingly.

## Start the development server

Expand All @@ -49,8 +47,12 @@ Run the following command to build the production bundles with webpack:
$ yarn build
```

## Adjust the configuration for production

The `custom-application-config.json` has a `env.production` configuration object. When you're ready to deploy the application to production, make sure to provide the URL where the Custom Application is hosted.

## Linting, formatting, and so on

We only provide the minimal scripts and tooling to _start_, _test_ and _build_ the application. If you want to add more development tooling such as **linters**, **prettier**, etc. you need to provide those on your own.
We only provide the minimal scripts and tooling to _start_, _test_, and _build_ the application. If you want to add more development tooling such as **linters**, **prettier**, etc. you need to provide those on your own.

You can have a look at our setup in the [`merchant-center-application-kit`](https://github.com/commercetools/merchant-center-application-kit) repository to help you getting set up.
10 changes: 10 additions & 0 deletions application-templates/starter/custom-application-config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"name": "Custom Application Template Starter",
"entryPointUriPath": "examples-starter",
"cloudIdentifier": "gcp-eu",
"env": {
"production": {
"url": "https://<your_app_hostname>"
}
}
}
9 changes: 0 additions & 9 deletions application-templates/starter/env.json

This file was deleted.

7 changes: 0 additions & 7 deletions application-templates/starter/headers.json

This file was deleted.

2 changes: 1 addition & 1 deletion application-templates/starter/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"scripts": {
"build": "mc-scripts build",
"start": "dotenv -- mc-scripts start",
"start:prod:local": "NODE_ENV=production dotenv -- mc-http-server --config=$(pwd)/env.json --headers=$(pwd)/headers.json --use-local-assets",
"start:prod:local": "NODE_ENV=production MC_APP_ENV=development dotenv -- mc-http-server --use-local-assets",
"i18n:build": "mc-scripts extract-intl --output-path=$(pwd)/src/i18n/data 'src/**/!(*.spec).js' --build-translations",
"test": "jest --config jest.test.config.js",
"test:watch": "jest --config jest.test.config.js --watch",
Expand Down
2 changes: 1 addition & 1 deletion jest.eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ module.exports = {
runner: 'jest-runner-eslint',
displayName: 'eslint',
moduleFileExtensions: ['js', 'ts', 'tsx'],
modulePathIgnorePatterns: ['dist', 'public'],
modulePathIgnorePatterns: ['build', 'dist', 'public'],
testMatch: ['<rootDir>/**/*.js', '<rootDir>/**/*.ts', '<rootDir>/**/*.tsx'],
watchPlugins: ['jest-watch-typeahead/filename', 'jest-watch-master'],
};
1 change: 1 addition & 0 deletions jest.stylelint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ module.exports = {
displayName: 'stylelint',
moduleFileExtensions: ['css', 'js'],
modulePathIgnorePatterns: [
'build',
'dist',
'public',
'.spec.js',
Expand Down
2 changes: 1 addition & 1 deletion jest.test.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ module.exports = {
'playground',
'node_modules',
],
modulePathIgnorePatterns: ['examples'],
modulePathIgnorePatterns: ['build', 'dist', 'public', 'examples'],
transformIgnorePatterns: [
// Transpile also our local packages as they are only symlinked.
'node_modules/(?!(@commercetools-[frontend|backend]+)/)',
Expand Down
1 change: 1 addition & 0 deletions jest.text.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ module.exports = {
runner: 'jest-runner-executor',
displayName: 'vale',
moduleFileExtensions: ['md', 'mdx'],
modulePathIgnorePatterns: ['build', 'dist', 'public'],
testMatch: ['<rootDir>/website/**/*.md', '<rootDir>/website/**/*.mdx'],
watchPlugins: ['jest-watch-typeahead/filename', 'jest-watch-master'],
};
3 changes: 3 additions & 0 deletions lint-staged.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,7 @@ module.exports = {
// For that reason, we move the `--onlyChanged` flag next to it.
'yarn lint:css --reporters=jest-silent-reporter --onlyChanged',
],
'packages/application-config/schema.json': [
'bash -c "yarn --cwd packages/application-config build:schema"',
],
};
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"private": true,
"scripts": {
"auth": "npm_config_registry=https://registry.npmjs.org npm whoami",
"clean": "lerna exec 'rm -rf dist'",
"clean": "lerna exec 'rm -rf build dist'",
"i18n:build": "./packages/mc-scripts/bin/mc-scripts.js extract-intl --output-path=$(pwd)/packages/i18n/data 'packages/**/!(*.spec|*.d).{js,ts,tsx}'",
"l10n:build": "pushd packages/l10n; yarn generate-data",
"lint": "jest --projects jest.eslint.config.js jest.stylelint.config.js jest.text.config.js",
Expand Down
1 change: 1 addition & 0 deletions packages/application-config/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
build
21 changes: 21 additions & 0 deletions packages/application-config/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2020 commercetools GmbH

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
50 changes: 50 additions & 0 deletions packages/application-config/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# @commercetools-frontend/application-config

<p align="center">
<a href="https://www.npmjs.com/package/@commercetools-frontend/application-config"><img src="https://badgen.net/npm/v/@commercetools-frontend/application-config" alt="Latest release (latest dist-tag)" /></a> <a href="https://www.npmjs.com/package/@commercetools-frontend/application-config"><img src="https://badgen.net/npm/v/@commercetools-frontend/application-config/next" alt="Latest release (next dist-tag)" /></a> <a href="https://bundlephobia.com/result?p=@commercetools-frontend/application-config"><img src="https://badgen.net/bundlephobia/minzip/@commercetools-frontend/application-config" alt="Minified + GZipped size" /></a> <a href="https://github.com/commercetools/merchant-center-application-kit/blob/master/LICENSE"><img src="https://badgen.net/github/license/commercetools/merchant-center-application-kit" alt="GitHub license" /></a>
</p>

This package contains utilities for configuring Custom Applications.

## Install

```bash
$ npm install --save @commercetools-frontend/application-config
```

## Configuration format

A Custom Application must be configured with a single JSON configuration file. The file name can be one of:

- `.custom-application-configrc`
- `.custom-application-config.json`
- `custom-application-config.json`

The file is automatically loaded, as long as it is found in the project's root folder. For that, the package uses the [cosmiconfig](https://www.npmjs.com/package/cosmiconfig) library.

The configuration file is in the format of a JSON schema that is also part of this package. The configuration file itself is validated when starting the Custom Application against the JSON schema.

By default the configuration file uses the `NODE_ENV` variable to determine which configuration to use. This can be overridden by using the custom environment variable `MC_APP_ENV`.

In the [test fixtures](./test/fixtures) folder you can see some examples of configuration.

### JSON Schema

To enable JSON schema validation for the Custom Application configuration, you can add a reference as a URL to the `schema.json` file provided in this package.

**Example setup for VSCode**

In the VSCode settings (either user settings or workspace settings), reference the schema JSON as described below:

```json
"json.schemas": [
{
"fileMatch": [
"/.custom-application-configrc",
"/.custom-application-config.json",
"/custom-application-config.json"
],
"url": "https://unpkg.com/@commercetools-frontend/application-config/schema.json"
}
]
```
Loading

1 comment on commit 728024c

@vercel
Copy link

@vercel vercel bot commented on 728024c Jul 16, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.