Merge pull request #2 from Inforitnl/update/from-upstream

Update/from upstream
This commit is contained in:
Rick van Lieshout 2022-07-25 11:16:50 +02:00 committed by GitHub
commit 126c80c7c4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 1478 additions and 1532 deletions

2
.nvmrc
View File

@ -1 +1 @@
lts/* 18.6.0

View File

@ -2,11 +2,13 @@
"cSpell.words": [ "cSpell.words": [
"browserslist", "browserslist",
"camelcase", "camelcase",
"deepmerge",
"flexbugs", "flexbugs",
"Immer", "Immer",
"languagedetector", "languagedetector",
"luxon", "luxon",
"pmmmwh", "pmmmwh",
"preinstall",
"reduxjs", "reduxjs",
"SVGR", "SVGR",
"tailwindcss", "tailwindcss",

View File

@ -4,6 +4,12 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [0.4.0] - 2022-07-25
- Added the possibility to override partial configs during deployments
- Added default output to jest (for terminal output...)
- Upgraded npm packages. Left jest on 27 because of breaking changes in 28
## [0.3.2] - 2022-07-19 ## [0.3.2] - 2022-07-19
- e2e step now starts a server before running tests - e2e step now starts a server before running tests

View File

@ -18,6 +18,9 @@ Includes:
- [Getting started](#getting-started) - [Getting started](#getting-started)
- [Project structure](#project-structure) - [Project structure](#project-structure)
- ["Forking" outside of Github](#forking-outside-of-github) - ["Forking" outside of Github](#forking-outside-of-github)
- [Configuration](#configuration)
- [Using the `config.ts` file](#using-the-configts-file)
- [adding values](#adding-values)
<!-- tocstop --> <!-- tocstop -->
@ -37,7 +40,11 @@ Only the important files are shown
├── config # tool configuration ├── config # tool configuration
├── cypress # e2e tests ├── cypress # e2e tests
├── dist # production version ├── dist # production version
├── public # directory with public files (config, icons, etc) ├── public
├── public # directory with public files (config, icons, etc), will be copied to dist
│ ├── i18n # directory to house i18n language files
│ ├── config.js # default runtime application config
│ └── configOverride.js # default config overrides.
├── scripts # Modified default create-react-app scripts ├── scripts # Modified default create-react-app scripts
├── src # application source ├── src # application source
│ ├── app # redux-toolkit hooks + store │ ├── app # redux-toolkit hooks + store
@ -60,3 +67,40 @@ Go into your existing repo and execute the following commands:
3. `git push` 3. `git push`
Then, when you need to sync again you can repeat step 2 and 3 Then, when you need to sync again you can repeat step 2 and 3
## Configuration
This starter kit comes with runtime configuration out-of-the-box.
It achieves this with 2 config files in the public directory: `config.js` and `configOverrides.js`.
`config.js` is meant to be filled with a default for all of your application's runtime configurations.
`configOverrides.js` is meant to be replaced during deployment with environment specific runtime overrides.
### Using the `config.ts` file
To use the config you import `Config` from `config.ts` and use the typed object:
```tsx
import { Config } from "../config";
import { FunctionComponent } from "react";
export const Navbar: FunctionComponent<{}> = () => {
return <h1>{JSON.stringify(Config)}</h1>;
};
```
### adding values
To add a value to the runtime config you have to take 2 steps:
1. Add a type to the `RuntimeConfig` type in [src/infrastructure/config/RunTimeConfig.ts](./src/infrastructure/config/RunTimeConfig.ts)
```tsx
type RunTimeConfig = {
version: number;
name: string;
myNewKey: string;
};
```
2. Add a key (if required) to [public/config.js](./public/config.js)

View File

@ -4,6 +4,7 @@ const config = {
roots: ["<rootDir>/src"], roots: ["<rootDir>/src"],
collectCoverageFrom: ["src/**/*.{js,jsx,ts,tsx}", "!src/**/*.d.ts"], collectCoverageFrom: ["src/**/*.{js,jsx,ts,tsx}", "!src/**/*.d.ts"],
reporters: [ reporters: [
"default",
[ [
"jest-junit", "jest-junit",
{ {

2789
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
{ {
"name": "react-starter-kit", "name": "react-starter-kit",
"version": "0.2.0", "version": "0.4.0",
"description": "A modern, create-react-app-based, starter kit for React projects", "description": "A modern, create-react-app-based, starter kit for React projects",
"keywords": [ "keywords": [
"react", "react",
@ -35,7 +35,7 @@
"organize-package-json": "npx format-package -w && npx sort-package-json", "organize-package-json": "npx format-package -w && npx sort-package-json",
"pretty-quick": "pretty-quick --staged", "pretty-quick": "pretty-quick --staged",
"start": "node scripts/start.js", "start": "node scripts/start.js",
"test": "node scripts/test.js", "test": "node scripts/test.js --verbose",
"test-ci": "node scripts/test.js --ci --coverage", "test-ci": "node scripts/test.js --ci --coverage",
"test-live-coverage": " concurrently --kill-others \"npm run test-with-coverage\" \"npx http-server -c-1 coverage/lcov-report\"", "test-live-coverage": " concurrently --kill-others \"npm run test-with-coverage\" \"npx http-server -c-1 coverage/lcov-report\"",
"test-with-coverage": "node scripts/test.js --coverage", "test-with-coverage": "node scripts/test.js --coverage",
@ -46,6 +46,7 @@
}, },
"dependencies": { "dependencies": {
"@reduxjs/toolkit": "^1.8.3", "@reduxjs/toolkit": "^1.8.3",
"deepmerge": "^4.2.2",
"i18next-http-backend": "^1.4.1", "i18next-http-backend": "^1.4.1",
"luxon": "^2.4.0", "luxon": "^2.4.0",
"react": "^18.2.0", "react": "^18.2.0",
@ -57,16 +58,16 @@
"tailwindcss": "^3.1.6" "tailwindcss": "^3.1.6"
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "^7.18.6", "@babel/core": "^7.18.9",
"@mastermindzh/prettier-config": "^1.0.0", "@mastermindzh/prettier-config": "^1.0.0",
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.7", "@pmmmwh/react-refresh-webpack-plugin": "^0.5.7",
"@svgr/webpack": "^5.5.0", "@svgr/webpack": "^5.5.0",
"@testing-library/jest-dom": "^5.16.4", "@testing-library/jest-dom": "^5.16.4",
"@testing-library/react": "^13.3.0", "@testing-library/react": "^13.3.0",
"@testing-library/user-event": "^14.2.5", "@testing-library/user-event": "^14.3.0",
"@types/jest": "^28.1.6", "@types/jest": "^28.1.6",
"@types/luxon": "^2.3.2", "@types/luxon": "^3.0.0",
"@types/node": "^18.0.6", "@types/node": "^18.6.1",
"@types/react": "^18.0.15", "@types/react": "^18.0.15",
"@types/react-dom": "^18.0.6", "@types/react-dom": "^18.0.6",
"babel-jest": "^27.4.2", "babel-jest": "^27.4.2",
@ -77,13 +78,13 @@
"browserslist": "^4.21.2", "browserslist": "^4.21.2",
"camelcase": "^6.2.1", "camelcase": "^6.2.1",
"case-sensitive-paths-webpack-plugin": "^2.4.0", "case-sensitive-paths-webpack-plugin": "^2.4.0",
"concurrently": "^7.2.2", "concurrently": "^7.3.0",
"css-loader": "^6.7.1", "css-loader": "^6.7.1",
"css-minimizer-webpack-plugin": "^3.2.0", "css-minimizer-webpack-plugin": "^3.2.0",
"cypress": "^10.3.0", "cypress": "^10.3.1",
"dotenv": "^10.0.0", "dotenv": "^10.0.0",
"dotenv-expand": "^5.1.0", "dotenv-expand": "^5.1.0",
"eslint": "^8.3.0", "eslint": "^8.20.0",
"eslint-config-prettier": "^8.5.0", "eslint-config-prettier": "^8.5.0",
"eslint-config-react-app": "^7.0.1", "eslint-config-react-app": "^7.0.1",
"eslint-plugin-cypress": "^2.12.1", "eslint-plugin-cypress": "^2.12.1",
@ -100,6 +101,7 @@
"identity-obj-proxy": "^3.0.0", "identity-obj-proxy": "^3.0.0",
"immer": "^9.0.15", "immer": "^9.0.15",
"jest": "^27.4.3", "jest": "^27.4.3",
"jest-environment-jsdom": "^27.4.3",
"jest-junit": "^14.0.0", "jest-junit": "^14.0.0",
"jest-resolve": "^27.4.2", "jest-resolve": "^27.4.2",
"jest-watch-typeahead": "^1.0.0", "jest-watch-typeahead": "^1.0.0",

View File

@ -1,11 +1,13 @@
const config = { const defaultConfig = {
version: "0.1.0", version: "0.1.0",
name: "React-starter-kit",
}; };
// ignore this :)
try { try {
window.config = config; window.defaultConfig = defaultConfig;
if (module) { if (module) {
module.exports = config; module.exports = defaultConfig;
} }
} catch { } catch {
// ignore // ignore

17
public/configOverride.js Normal file
View File

@ -0,0 +1,17 @@
/**
* This is the config override file.
* This file is meant to be replaced during deployment with override values compared to the regular config.js
* For development purposes this file can be completely empty
*/
const configOverride = {};
// ignore this :)
try {
window.configOverride = configOverride;
if (module) {
module.exports = configOverride;
}
} catch {
// ignore
}

View File

@ -4,7 +4,7 @@
}, },
"navBar": { "navBar": {
"intro": "Our fancy header with navigation.", "intro": "Our fancy header with navigation.",
"version": "App version:", "version": "version:",
"currentDate": "Today's date: {{date, formattedDate}}" "currentDate": "Today's date: {{date, formattedDate}}"
}, },
"nav": { "nav": {

View File

@ -4,7 +4,7 @@
}, },
"navBar": { "navBar": {
"intro": "Een fancy header met navigatie", "intro": "Een fancy header met navigatie",
"version": "Aplicatie versie:", "version": "versie:",
"currentDate": "De datum van vandaag: {{date, formattedDate}}" "currentDate": "De datum van vandaag: {{date, formattedDate}}"
}, },
"nav": { "nav": {

View File

@ -1,18 +1,22 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head>
<meta charset="utf-8" /> <head>
<link rel="icon" href="%PUBLIC_URL%/icon/favicon.ico" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" /> <link rel="icon" href="%PUBLIC_URL%/icon/favicon.ico" />
<meta name="theme-color" content="#000000" /> <meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="description" content="React base project" /> <meta name="theme-color" content="#000000" />
<link rel="apple-touch-icon" href="%PUBLIC_URL%/icon/apple-icon-180x180.png" /> <meta name="description" content="React base project" />
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" /> <link rel="apple-touch-icon" href="%PUBLIC_URL%/icon/apple-icon-180x180.png" />
<title>React Base App</title> <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<script src="%PUBLIC_URL%/config.js"></script> <title>React Base App</title>
</head> <script src="%PUBLIC_URL%/config.js"></script>
<body> <script src="%PUBLIC_URL%/configOverride.js"></script>
<noscript>You need to enable JavaScript to run this app.</noscript> </head>
<div id="root"></div>
</body> <body>
</html> <noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
</body>
</html>

View File

@ -0,0 +1,4 @@
export interface RunTimeConfig {
version: number;
name: string;
}

15
src/config/config.ts Normal file
View File

@ -0,0 +1,15 @@
import deepmerge from "deepmerge";
/**
* gets and merges both the regular config and the override config from the window
* into window.mergedConfig
*/
export const mergeConfigs = () => {
if (!window.mergedConfig) {
window.mergedConfig = deepmerge(window.defaultConfig, window.configOverride ?? {});
}
};
mergeConfigs();
export const Config = window.mergedConfig;

1
src/config/index.ts Normal file
View File

@ -0,0 +1 @@
export * from "./config";

View File

@ -1,5 +0,0 @@
type RunTimeConfig = {
version: number;
};
export const Config = (window as any).config as RunTimeConfig;

View File

@ -2,7 +2,7 @@ import { DateTime } from "luxon";
import { FunctionComponent } from "react"; import { FunctionComponent } from "react";
import { Trans, useTranslation } from "react-i18next"; import { Trans, useTranslation } from "react-i18next";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
import { Config } from "../config"; import { Config } from "../../config";
import "./Navbar.css"; import "./Navbar.css";
type Props = {}; type Props = {};
@ -13,7 +13,7 @@ export const Navbar: FunctionComponent<Props> = () => {
<h1>{translate("navBar.intro")}</h1> <h1>{translate("navBar.intro")}</h1>
<p> <p>
{/* trans can also be used to translate */} {/* trans can also be used to translate */}
<Trans i18nKey="navBar.version">App version:</Trans> {Config.name} <Trans i18nKey="navBar.version">version:</Trans>
{JSON.stringify(Config.version)} {JSON.stringify(Config.version)}
</p> </p>

View File

@ -4,68 +4,68 @@
declare namespace NodeJS { declare namespace NodeJS {
interface ProcessEnv { interface ProcessEnv {
readonly NODE_ENV: 'development' | 'production' | 'test'; readonly NODE_ENV: "development" | "production" | "test";
readonly PUBLIC_URL: string; readonly PUBLIC_URL: string;
} }
} }
declare module '*.avif' { declare module "*.avif" {
const src: string; const src: string;
export default src; export default src;
} }
declare module '*.bmp' { declare module "*.bmp" {
const src: string; const src: string;
export default src; export default src;
} }
declare module '*.gif' { declare module "*.gif" {
const src: string; const src: string;
export default src; export default src;
} }
declare module '*.jpg' { declare module "*.jpg" {
const src: string; const src: string;
export default src; export default src;
} }
declare module '*.jpeg' { declare module "*.jpeg" {
const src: string; const src: string;
export default src; export default src;
} }
declare module '*.png' { declare module "*.png" {
const src: string; const src: string;
export default src; export default src;
} }
declare module '*.webp' { declare module "*.webp" {
const src: string; const src: string;
export default src; export default src;
} }
declare module '*.svg' { declare module "*.svg" {
import * as React from 'react'; import * as React from "react";
export const ReactComponent: React.FunctionComponent<React.SVGProps< export const ReactComponent: React.FunctionComponent<
SVGSVGElement React.SVGProps<SVGSVGElement> & { title?: string }
> & { title?: string }>; >;
const src: string; const src: string;
export default src; export default src;
} }
declare module '*.module.css' { declare module "*.module.css" {
const classes: { readonly [key: string]: string }; const classes: { readonly [key: string]: string };
export default classes; export default classes;
} }
declare module '*.module.scss' { declare module "*.module.scss" {
const classes: { readonly [key: string]: string }; const classes: { readonly [key: string]: string };
export default classes; export default classes;
} }
declare module '*.module.sass' { declare module "*.module.sass" {
const classes: { readonly [key: string]: string }; const classes: { readonly [key: string]: string };
export default classes; export default classes;
} }

View File

@ -4,4 +4,5 @@
// learn more: https://github.com/testing-library/jest-dom // learn more: https://github.com/testing-library/jest-dom
import "@testing-library/jest-dom/extend-expect"; import "@testing-library/jest-dom/extend-expect";
(window as any).config = require("./../public/config"); window.defaultConfig = require("./../public/config");
window.configOverride = require("./../public/configOverride");

11
src/types/globals.d.ts vendored Normal file
View File

@ -0,0 +1,11 @@
import { RunTimeConfig } from "./../config/RunTimeConfig";
declare global {
interface Window {
mergedConfig: RunTimeConfig;
defaultConfig: RunTimeConfig;
configOverride: Partial<RunTimeConfig>;
}
}
export {};