refactor: monorepo setup with lerna (#243)

This commit is contained in:
Daniel Lautzenheiser 2022-12-15 13:44:49 -05:00 committed by GitHub
parent dac29fbf3c
commit 504d95c34f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
706 changed files with 16571 additions and 142 deletions

View File

@ -1,15 +1,11 @@
name: Core
name: Build
on:
workflow_dispatch:
push:
branches: ["main"]
paths:
- core/**
pull_request:
branches: ["main"]
paths:
- core/**
jobs:
build:
@ -22,16 +18,18 @@ jobs:
uses: actions/setup-node@v3
with:
cache: yarn
cache-dependency-path: core/yarn.lock
cache-dependency-path: |
yarn.lock
packages/app/yarn.lock
packages/core/yarn.lock
packages/docs/yarn.lock
node-version: 16
- name: Install
working-directory: ./core
run: |
yarn install --frozen-lockfile
- name: Build
working-directory: ./core
run: |
yarn build
@ -45,16 +43,18 @@ jobs:
uses: actions/setup-node@v3
with:
cache: yarn
cache-dependency-path: core/yarn.lock
cache-dependency-path: |
yarn.lock
packages/app/yarn.lock
packages/core/yarn.lock
packages/docs/yarn.lock
node-version: 16
- name: Install
working-directory: ./core
run: |
yarn install --frozen-lockfile
- name: Lint
working-directory: ./core
run: |
yarn lint
@ -68,16 +68,18 @@ jobs:
uses: actions/setup-node@v3
with:
cache: yarn
cache-dependency-path: core/yarn.lock
cache-dependency-path: |
yarn.lock
packages/app/yarn.lock
packages/core/yarn.lock
packages/docs/yarn.lock
node-version: 16
- name: Install
working-directory: ./core
run: |
yarn install --frozen-lockfile
- name: Test
working-directory: ./core
run: |
yarn test:ci
@ -91,15 +93,17 @@ jobs:
uses: actions/setup-node@v3
with:
cache: yarn
cache-dependency-path: core/yarn.lock
cache-dependency-path: |
yarn.lock
packages/app/yarn.lock
packages/core/yarn.lock
packages/docs/yarn.lock
node-version: 16
- name: Install
working-directory: ./core
run: |
yarn install --frozen-lockfile
- name: Test
working-directory: ./core
run: |
yarn test:integration:ci

View File

@ -14,15 +14,9 @@ name: "CodeQL"
on:
push:
branches: ["main"]
paths:
- core/**
- docs/**
pull_request:
# The branches below must be a subset of the branches above
branches: ["main"]
paths:
- core/**
- docs/**
schedule:
- cron: "0 9 * * 4"

View File

@ -1,54 +0,0 @@
name: Docs
on:
workflow_dispatch:
push:
branches: ["main"]
paths:
- docs/**
pull_request:
branches: ["main"]
paths:
- docs/**
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node
uses: actions/setup-node@v3
with:
cache: yarn
cache-dependency-path: docs/yarn.lock
node-version: 16
- name: Install
working-directory: ./docs
run: |
yarn install --frozen-lockfile
- name: Lint
working-directory: ./docs
run: |
yarn lint
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
integration_tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3

1
.gitignore vendored
View File

@ -1,2 +1,3 @@
# dependencies
/node_modules
.log

View File

@ -11,60 +11,67 @@ For details on contributing to documentation, see [Website Directory Readme](htt
### Install dependencies
> Only required on the first run, subsequent runs can use `yarn start` to both bootstrap and run the development server.
> Only required on the first run, subsequent runs can use `yarn dev` to both bootstrap and run the development server.
```sh
git clone https://github.com/StaticJsCMS/static-cms
cd static-cms
yarn
cd core
yarn
```
### Run core locally
> In `core` directory
### Run locally
```sh
cd core # if not there already
yarn start
yarn dev
```
## Available scripts
### start
### dev
Starts the development server. This task runs both the `clean` and `develop` scripts.
Starts the development server.
```sh
cd core # if not there already
yarn start
```
### clean
Removes the `dist` directory.
```sh
cd core # if not there already
yarn clean
yarn dev
```
### build
Runs the `clean` script and builds the @static-cms/core.
Runs the builds for packages.
```sh
cd core # if not there already
yarn build
```
### test
Runs unit tests for packages.
```sh
yarn test
```
### test:integration
Runs integration tests for packages.
```sh
yarn test:integration
```
### lint
Lints core and docs according to our style guidelines.
```sh
yarn lint
```
### format
Formats code and docs according to our style guidelines.
Formats core and docs according to our style guidelines.
```sh
cd core # if not there already
yarn format
```
@ -86,7 +93,7 @@ Static CMS uses the [Forking Workflow](https://www.atlassian.com/git/tutorials/c
## Debugging
`yarn start` spawns a development server and uses `dev-test/config.yml` and `dev-test/index.html` to serve the CMS.
`yarn dev` spawns a development server and uses `dev-test/config.yml` and `dev-test/index.html` to serve the CMS.
In order to debug a specific issue follow the next steps:
1. Replace `dev-test/config.yml` with the relevant `config.yml`. If you want to test the backend, make sure that the `backend` property of the config indicates which backend you use (Github, Gitlab, Bitbucket etc) and path to the repo.
@ -97,7 +104,7 @@ backend:
repo: owner-name/repo-name
```
2. Run `yarn start`
2. Run `yarn dev`
3. Open `http://localhost:8080/` in the browser and you should have access to the CMS
### Debugging Git Gateway

5
lerna.json Normal file
View File

@ -0,0 +1,5 @@
{
"$schema": "node_modules/lerna/schemas/lerna-schema.json",
"useWorkspaces": true,
"version": "0.0.0"
}

20
nx.json Normal file
View File

@ -0,0 +1,20 @@
{
"tasksRunnerOptions": {
"default": {
"runner": "nx/tasks-runners/default",
"options": {
"cacheableOperations": ["build", "test"]
}
}
},
"targetDefaults": {
"build": {
"dependsOn": ["^build"]
},
"dev": {
"dependsOn": [
"^build"
]
}
}
}

View File

@ -1,9 +1,27 @@
{
"name": "static-cms",
"private": true,
"scripts": {
"build": "lerna run build",
"dev": "lerna run dev --scope=@staticcms/core",
"docs": "lerna run dev --scope=docs",
"format": "lerna run format",
"lint": "lerna run lint",
"prepare": "husky install",
"publish": "lerna run publish",
"test:ci": "lerna run test:ci",
"test:integration:ci": "lerna run test:integration:ci",
"test:integration": "lerna run test:integration",
"test": "lerna run test"
},
"devDependencies": {
"husky": "8.0.2",
"lint-staged": "13.1.0"
"lerna": "6.1.0",
"lint-staged": "13.1.0",
"react": "18.2.0",
"react-dom": "18.2.0"
},
"scripts": {
"prepare": "husky install"
}
"workspaces": [
"packages/*"
]
}

View File

@ -1,3 +1,4 @@
node_modules
dist
dev-test
dev-test
.js

105
packages/app/package.json Normal file
View File

@ -0,0 +1,105 @@
{
"name": "@staticcms/app",
"version": "1.0.0-beta4",
"license": "MIT",
"description": "Static CMS application.",
"repository": "https://github.com/StaticJsCMS/static-cms",
"bugs": "https://github.com/StaticJsCMS/static-cms/issues",
"keywords": [
"simple",
"cms",
"app"
],
"scripts": {
"build:webpack": "webpack",
"build": "cross-env NODE_ENV=production run-s clean build:webpack",
"clean": "rimraf dist dev-test/dist",
"prepublishOnly": "yarn build ",
"prepack": "cp ../../README.md ./",
"postpack": "rm ./README.md"
},
"main": "dist/static-cms-app.js",
"files": [
"dist/**/*"
],
"browserslist": [
"last 2 Chrome versions",
"last 2 ChromeAndroid versions",
"last 2 Edge versions",
"last 2 Firefox versions",
"last 2 iOS versions",
"last 2 Opera versions",
"last 2 Safari versions"
],
"dependencies": {
"@babel/eslint-parser": "7.19.1",
"@babel/runtime": "7.20.6",
"@emotion/babel-preset-css-prop": "11.10.0",
"@staticcms/core": "1.0.0-beta4",
"buffer": "6.0.3",
"react": "18.2.0",
"react-dom": "18.2.0",
"stream-browserify": "3.0.0",
"ts-loader": "9.4.2"
},
"devDependencies": {
"@babel/cli": "7.19.3",
"@babel/core": "7.20.5",
"@babel/plugin-proposal-class-properties": "7.18.6",
"@babel/plugin-proposal-export-default-from": "7.18.10",
"@babel/plugin-proposal-nullish-coalescing-operator": "7.18.6",
"@babel/plugin-proposal-numeric-separator": "7.18.6",
"@babel/plugin-proposal-object-rest-spread": "7.20.2",
"@babel/plugin-proposal-optional-chaining": "7.18.9",
"@babel/plugin-syntax-dynamic-import": "7.8.3",
"@babel/preset-env": "7.20.2",
"@babel/preset-react": "7.18.6",
"@babel/preset-typescript": "7.18.6",
"@emotion/eslint-plugin": "11.10.0",
"@emotion/jest": "11.10.5",
"@types/node": "16.18.9",
"@types/react": "18.0.26",
"@types/react-dom": "18.0.9",
"@typescript-eslint/eslint-plugin": "5.46.1",
"@typescript-eslint/parser": "5.46.1",
"babel-core": "7.0.0-bridge.0",
"babel-loader": "9.1.0",
"babel-plugin-emotion": "11.0.0",
"babel-plugin-inline-json-import": "0.3.2",
"babel-plugin-inline-react-svg": "2.0.1",
"babel-plugin-lodash": "3.3.4",
"babel-plugin-transform-builtin-extend": "1.1.2",
"babel-plugin-transform-define": "2.1.0",
"babel-plugin-transform-export-extensions": "6.22.0",
"babel-plugin-transform-inline-environment-variables": "0.4.4",
"cross-env": "7.0.3",
"dotenv": "16.0.3",
"eslint": "8.29.0",
"eslint-import-resolver-typescript": "3.5.2",
"eslint-plugin-cypress": "2.12.1",
"eslint-plugin-import": "2.26.0",
"eslint-plugin-prettier": "4.2.1",
"eslint-plugin-react": "7.31.11",
"eslint-plugin-react-hooks": "4.6.0",
"eslint-plugin-unicorn": "45.0.2",
"npm-run-all": "4.1.5",
"postcss": "8.4.20",
"postcss-scss": "4.0.6",
"prettier": "2.8.1",
"source-map-loader": "4.0.1",
"style-loader": "3.3.1",
"to-string-loader": "1.2.0",
"tsconfig-paths-webpack-plugin": "4.0.0",
"typescript": "4.9.4",
"webpack": "5.75.0",
"webpack-cli": "5.0.1"
},
"publishConfig": {
"access": "public",
"registry": "https://registry.npmjs.org"
},
"lint-staged": {
"*.ts": "prettier --write",
"*.tsx": "prettier --write"
}
}

View File

@ -0,0 +1 @@
import '@staticcms/core';

View File

@ -0,0 +1,59 @@
{
"compilerOptions": {
"declaration": true,
"declarationDir": "dist",
"emitDeclarationOnly": true,
"jsx": "react",
"target": "ES2020",
"module": "ES2020",
"moduleResolution": "node",
"esModuleInterop": true,
"preserveSymlinks": true,
"noEmit": false,
"strict": true,
"isolatedModules": true,
"skipLibCheck": true,
"allowJs": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"baseUrl": "./",
"lib": ["DOM", "es6", "ES2015", "ES2020"],
"paths": {
"@staticcms/boolean": ["../core/src/widgets/boolean"],
"@staticcms/boolean/*": ["../core/src/widgets/boolean/*"],
"@staticcms/code": ["../core/src/widgets/code"],
"@staticcms/code/*": ["../core/src/widgets/code/*"],
"@staticcms/colorstring": ["../core/src/widgets/colorstring"],
"@staticcms/colorstring/*": ["../core/src/widgets/colorstring/*"],
"@staticcms/datetime": ["../core/src/widgets/datetime"],
"@staticcms/datetime/*": ["../core/src/widgets/datetime/*"],
"@staticcms/file": ["../core/src/widgets/file"],
"@staticcms/file/*": ["../core/src/widgets/file/*"],
"@staticcms/image": ["../core/src/widgets/image"],
"@staticcms/image/*": ["../core/src/widgets/image/*"],
"@staticcms/list": ["../core/src/widgets/list"],
"@staticcms/list/*": ["../core/src/widgets/list/*"],
"@staticcms/map": ["../core/src/widgets/map"],
"@staticcms/map/*": ["../core/src/widgets/map/*"],
"@staticcms/markdown": ["../core/src/widgets/markdown"],
"@staticcms/markdown/*": ["../core/src/widgets/markdown/*"],
"@staticcms/number": ["../core/src/widgets/number"],
"@staticcms/number/*": ["../core/src/widgets/number/*"],
"@staticcms/object": ["../core/src/widgets/object"],
"@staticcms/object/*": ["../core/src/widgets/object/*"],
"@staticcms/relation": ["../core/src/widgets/relation"],
"@staticcms/relation/*": ["../core/src/widgets/relation/*"],
"@staticcms/select": ["../core/src/widgets/select"],
"@staticcms/select/*": ["../core/src/widgets/select/*"],
"@staticcms/string": ["../core/src/widgets/string"],
"@staticcms/string/*": ["../core/src/widgets/string/*"],
"@staticcms/text": ["../core/src/widgets/text"],
"@staticcms/text/*": ["../core/src/widgets/text/*"],
"@staticcms/core": ["../core/core/src/*"],
"@staticcms/core/*": ["../core/src/*"]
},
"types": ["@emotion/react/types/css-prop", "@types/jest", "@testing-library/jest-dom"]
},
"include": ["src/**/*"],
"exclude": ["node_modules", "**/*.spec.ts"]
}

View File

@ -7,13 +7,12 @@ const isProduction = process.env.NODE_ENV === 'production';
const devServerPort = parseInt(process.env.STATIC_CMS_DEV_SERVER_PORT || `${8080}`);
function moduleNameToPath(libName) {
return path.resolve(__dirname, 'node_modules', libName);
return path.resolve(__dirname, '..', '..', 'node_modules', libName);
}
module.exports = {
entry: './src/index.ts',
mode: isProduction ? 'production' : 'development',
devtool: 'source-map',
module: {
rules: [
{

View File

@ -0,0 +1,4 @@
node_modules
dist
dev-test
.js

131
packages/core/.eslintrc.js Normal file
View File

@ -0,0 +1,131 @@
module.exports = {
parser: '@babel/eslint-parser',
extends: [
'eslint:recommended',
'plugin:react/recommended',
'plugin:cypress/recommended',
'prettier',
'plugin:import/recommended',
],
env: {
es6: true,
browser: true,
node: true,
jest: true,
'cypress/globals': true,
},
globals: {
STATIC_CMS_CORE_VERSION: false,
CMS_ENV: false,
},
rules: {
'react-hooks/rules-of-hooks': 'error', // Checks rules of Hooks
'react-hooks/exhaustive-deps': 'warn', // Checks effect dependencies
'no-console': [0],
'react/prop-types': [0],
'react/require-default-props': 0,
'import/no-named-as-default': 0,
'react/react-in-jsx-scope': 'off',
'import/order': [
'error',
{
'newlines-between': 'always',
groups: [['builtin', 'external'], ['internal', 'parent', 'sibling', 'index'], ['type']],
},
],
'no-duplicate-imports': 'error',
'@emotion/no-vanilla': 'off',
'@emotion/import-from-emotion': 'error',
'@emotion/styled-import': 'error',
'require-atomic-updates': [0],
'object-shorthand': ['error', 'always'],
'prefer-const': [
'error',
{
destructuring: 'all',
},
],
'unicorn/prefer-string-slice': 'error',
'react/no-unknown-property': ['error', { ignore: ['css'] }],
'@typescript-eslint/no-unused-vars': [
'warn',
{
argsIgnorePattern: '^_',
varsIgnorePattern: '^_',
caughtErrorsIgnorePattern: '^_',
},
],
'@typescript-eslint/no-restricted-imports': [
'error',
{
patterns: [
{
group: ['@mui/*/*/*', '!@mui/material/test-utils/*'],
message: 'Do not import material imports as 3rd level imports',
allowTypeImports: true,
},
{
group: ['@mui/material', '!@mui/material/'],
message: 'Please import material imports as defaults or 2nd level imports',
allowTypeImports: true,
},
],
},
],
'import/prefer-default-export': 'error',
},
plugins: ['babel', '@emotion', 'cypress', 'unicorn', 'react-hooks'],
settings: {
react: {
version: 'detect',
},
'import/resolver': {
typescript: {}, // this loads <rootdir>/tsconfig.json to eslint
},
'import/core-modules': ['src'],
},
overrides: [
{
files: ['*.ts', '*.tsx'],
parser: '@typescript-eslint/parser',
extends: [
'eslint:recommended',
'plugin:react/recommended',
'plugin:cypress/recommended',
'plugin:@typescript-eslint/recommended',
'prettier',
'plugin:import/recommended',
'plugin:import/typescript',
],
parserOptions: {
ecmaVersion: 2018,
sourceType: 'module',
ecmaFeatures: {
jsx: true,
},
},
rules: {
'react/react-in-jsx-scope': 'off',
'react/prop-types': [0],
'react/require-default-props': 0,
'no-duplicate-imports': [0], // handled by @typescript-eslint
'@typescript-eslint/ban-types': [0], // TODO enable in future
'@typescript-eslint/no-non-null-assertion': [0],
'@typescript-eslint/consistent-type-imports': 'error',
'@typescript-eslint/explicit-function-return-type': [0],
'@typescript-eslint/explicit-module-boundary-types': [0],
'@typescript-eslint/no-duplicate-imports': 'error',
'@typescript-eslint/no-use-before-define': [
'error',
{ functions: false, classes: true, variables: true },
],
},
},
{
files: ['website/**/*'],
rules: {
'import/no-unresolved': [0],
},
},
],
};

View File

@ -0,0 +1,96 @@
const path = require('path');
const coreVersion = require('./package.json').version;
const isProduction = process.env.NODE_ENV === 'production';
const isTest = process.env.NODE_ENV === 'test';
const isESM = process.env.NODE_ENV === 'esm';
console.info('Build Package:', path.basename(process.cwd()));
const defaultPlugins = [
'lodash',
[
'babel-plugin-transform-builtin-extend',
{
globals: ['Error'],
},
],
'transform-export-extensions',
'@babel/plugin-proposal-class-properties',
'@babel/plugin-proposal-object-rest-spread',
'@babel/plugin-proposal-export-default-from',
'@babel/plugin-proposal-nullish-coalescing-operator',
'@babel/plugin-proposal-optional-chaining',
'@babel/plugin-syntax-dynamic-import',
'babel-plugin-inline-json-import',
];
const svgo = {
plugins: [
{
name: 'preset-default',
params: {
overrides: {
removeViewBox: false,
},
},
},
],
};
function presets() {
return [
'@babel/preset-react',
'@babel/preset-env',
[
'@emotion/babel-preset-css-prop',
{
autoLabel: 'always',
},
],
'@babel/typescript',
];
}
function plugins() {
if (isESM) {
return [
...defaultPlugins,
[
'transform-define',
{
STATIC_CMS_CORE_VERSION: `${coreVersion}`,
},
],
[
'inline-react-svg',
{
svgo,
},
],
];
}
if (isTest) {
return [
...defaultPlugins,
[
'inline-react-svg',
{
svgo,
},
],
];
}
if (!isProduction) {
return [...defaultPlugins];
}
return defaultPlugins;
}
module.exports = {
presets: presets(),
plugins: plugins(),
};

View File

Before

Width:  |  Height:  |  Size: 808 KiB

After

Width:  |  Height:  |  Size: 808 KiB

View File

Before

Width:  |  Height:  |  Size: 310 KiB

After

Width:  |  Height:  |  Size: 310 KiB

View File

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

View File

@ -0,0 +1,18 @@
const { pathsToModuleNameMapper } = require('ts-jest');
const { compilerOptions } = require('./tsconfig.base');
module.exports = {
preset: 'ts-jest',
transform: {
'\\.[jt]sx?$': ['ts-jest', { tsConfig: 'tsconfig.dev.json' }],
'^.+\\.svg$': './test/fileTransformer',
},
moduleNameMapper: {
...pathsToModuleNameMapper(compilerOptions.paths, { prefix: '<rootDir>/' }),
'\\.(css|less)$': '<rootDir>/src/__mocks__/styleMock.ts',
},
transformIgnorePatterns: [],
setupFiles: ['./test/setupEnv.js'],
testRegex: '\\.ispec\\.tsx?$',
};

View File

@ -0,0 +1,18 @@
const { pathsToModuleNameMapper } = require('ts-jest');
const { compilerOptions } = require('./tsconfig.base');
module.exports = {
preset: 'ts-jest',
transform: {
'\\.[jt]sx?$': ['ts-jest', { tsConfig: 'tsconfig.dev.json' }],
'^.+\\.svg$': './test/fileTransformer',
},
moduleNameMapper: {
...pathsToModuleNameMapper(compilerOptions.paths, { prefix: '<rootDir>/' }),
'\\.(css|less)$': '<rootDir>/src/__mocks__/styleMock.ts',
},
setupFiles: ['./test/setupEnv.js'],
testRegex: '\\.spec\\.tsx?$',
snapshotSerializers: ['@emotion/jest/serializer'],
};

View File

@ -15,7 +15,7 @@
"build:types": "tsc",
"build": "cross-env NODE_ENV=production run-s clean build:webpack build:types",
"clean": "rimraf dist dev-test/dist",
"develop": "webpack serve",
"dev": "run-s clean serve",
"format:prettier": "prettier \"src/**/*.{js,jsx,ts,tsx,css}\"",
"format": "run-s \"lint:js --fix --quiet\" \"format:prettier --write\"",
"lint-quiet": "run-p -c --aggregate-output \"lint:* --quiet\"",
@ -23,9 +23,9 @@
"lint:js": "eslint --color --ignore-path .gitignore \"src/**/*.{js,jsx,ts,tsx}\"",
"lint": "run-p -c --aggregate-output \"lint:*\"",
"prepublishOnly": "yarn build ",
"prepack": "cp ../README.md ./",
"prepack": "cp ../../README.md ./",
"postpack": "rm ./README.md",
"start": "run-s clean develop",
"serve": "webpack serve",
"test": "cross-env NODE_ENV=test jest",
"test:integration": "cross-env NODE_ENV=test jest -c jest.config.integration.js",
"test:ci": "cross-env NODE_ENV=test jest --maxWorkers=2",
@ -261,6 +261,10 @@
"webpack-cli": "5.0.1",
"webpack-dev-server": "4.11.1"
},
"peerDependencies": {
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
"publishConfig": {
"access": "public",
"registry": "https://registry.npmjs.org"

Some files were not shown because too many files have changed in this diff Show More