├── apps ├── .gitkeep ├── blog-api │ ├── src │ │ ├── app │ │ │ └── .gitkeep │ │ ├── assets │ │ │ └── .gitkeep │ │ ├── environments │ │ │ ├── environment.ts │ │ │ └── environment.prod.ts │ │ └── main.ts │ ├── .eslintrc │ ├── tsconfig.app.json │ ├── tsconfig.spec.json │ ├── tsconfig.json │ └── jest.config.js ├── blog │ ├── src │ │ ├── assets │ │ │ └── .gitkeep │ │ ├── favicon.ico │ │ ├── styles.css │ │ ├── environments │ │ │ ├── environment.prod.ts │ │ │ └── environment.ts │ │ ├── polyfills.ts │ │ ├── main.tsx │ │ ├── index.html │ │ └── app │ │ │ ├── star.svg │ │ │ ├── app.spec.tsx │ │ │ ├── app.tsx │ │ │ ├── app.css │ │ │ └── logo.svg │ ├── .babelrc │ ├── proxy.conf.json │ ├── babel-jest.config.json │ ├── tsconfig.app.json │ ├── tsconfig.json │ ├── jest.config.js │ ├── tsconfig.spec.json │ ├── .browserslistrc │ └── .eslintrc ├── todos-api │ ├── src │ │ ├── app │ │ │ └── .gitkeep │ │ ├── assets │ │ │ └── .gitkeep │ │ ├── environments │ │ │ ├── environment.ts │ │ │ └── environment.prod.ts │ │ └── main.ts │ ├── .eslintrc │ ├── tsconfig.app.json │ ├── tsconfig.spec.json │ ├── tsconfig.json │ └── jest.config.js ├── todos │ ├── src │ │ ├── assets │ │ │ └── .gitkeep │ │ ├── favicon.ico │ │ ├── environments │ │ │ ├── environment.prod.ts │ │ │ └── environment.ts │ │ ├── styles.css │ │ ├── polyfills.ts │ │ ├── main.tsx │ │ ├── index.html │ │ └── app │ │ │ ├── star.svg │ │ │ ├── app.spec.tsx │ │ │ ├── app.tsx │ │ │ ├── app.css │ │ │ └── logo.svg │ ├── .babelrc │ ├── proxy.conf.json │ ├── babel-jest.config.json │ ├── tsconfig.json │ ├── tsconfig.app.json │ ├── jest.config.js │ ├── tsconfig.spec.json │ ├── .browserslistrc │ └── .eslintrc └── todos-e2e │ ├── src │ ├── support │ │ ├── app.po.ts │ │ ├── index.ts │ │ └── commands.ts │ ├── fixtures │ │ └── example.json │ ├── integration │ │ └── app.spec.ts │ └── plugins │ │ └── index.js │ ├── tsconfig.json │ ├── tsconfig.e2e.json │ ├── .eslintrc │ └── cypress.json ├── libs ├── .gitkeep └── api-interfaces │ ├── src │ ├── index.ts │ └── lib │ │ └── api-interfaces.ts │ ├── .eslintrc │ ├── README.md │ ├── tsconfig.lib.json │ ├── tsconfig.json │ ├── tsconfig.spec.json │ └── jest.config.js ├── tools ├── schematics │ └── .gitkeep ├── tsconfig.tools.json └── externals │ └── prepare.js ├── .prettierrc ├── babel.config.json ├── .prettierignore ├── jest.config.js ├── .editorconfig ├── .gitignore ├── tsconfig.base.json ├── .github └── workflows │ ├── build-pr.yml │ ├── build-main.yml │ └── move-code.yml ├── externals └── todos │ ├── tsconfig.base.json │ ├── nx.json │ └── workspace.json ├── nx.json ├── .eslintrc ├── README.md ├── package.json └── workspace.json /apps/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /libs/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tools/schematics/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /apps/blog-api/src/app/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /apps/blog-api/src/assets/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /apps/blog/src/assets/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /apps/todos-api/src/app/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /apps/todos/src/assets/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /apps/todos-api/src/assets/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true 3 | } 4 | -------------------------------------------------------------------------------- /libs/api-interfaces/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './lib/api-interfaces'; 2 | -------------------------------------------------------------------------------- /apps/todos-e2e/src/support/app.po.ts: -------------------------------------------------------------------------------- 1 | export const getGreeting = () => cy.get('h1'); 2 | -------------------------------------------------------------------------------- /apps/blog/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["@nrwl/react/babel"], 3 | "plugins": [] 4 | } 5 | -------------------------------------------------------------------------------- /apps/todos/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["@nrwl/react/babel"], 3 | "plugins": [] 4 | } 5 | -------------------------------------------------------------------------------- /babel.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["@nrwl/web/babel"], 3 | "babelrcRoots": ["*"] 4 | } 5 | -------------------------------------------------------------------------------- /apps/blog-api/.eslintrc: -------------------------------------------------------------------------------- 1 | { "extends": "../../.eslintrc", "rules": {}, "ignorePatterns": ["!**/*"] } 2 | -------------------------------------------------------------------------------- /apps/blog/src/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Olivr/nx-copybara/HEAD/apps/blog/src/favicon.ico -------------------------------------------------------------------------------- /apps/todos-api/.eslintrc: -------------------------------------------------------------------------------- 1 | { "extends": "../../.eslintrc", "rules": {}, "ignorePatterns": ["!**/*"] } 2 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | # Add files here to ignore them from prettier formatting 2 | 3 | /dist 4 | /coverage 5 | -------------------------------------------------------------------------------- /apps/blog/src/styles.css: -------------------------------------------------------------------------------- 1 | /* You can add global styles to this file, and also import other style files */ 2 | -------------------------------------------------------------------------------- /apps/todos/src/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Olivr/nx-copybara/HEAD/apps/todos/src/favicon.ico -------------------------------------------------------------------------------- /libs/api-interfaces/.eslintrc: -------------------------------------------------------------------------------- 1 | { "extends": "../../.eslintrc", "rules": {}, "ignorePatterns": ["!**/*"] } 2 | -------------------------------------------------------------------------------- /libs/api-interfaces/src/lib/api-interfaces.ts: -------------------------------------------------------------------------------- 1 | export interface Message { 2 | message: string; 3 | } 4 | -------------------------------------------------------------------------------- /apps/blog-api/src/environments/environment.ts: -------------------------------------------------------------------------------- 1 | export const environment = { 2 | production: false, 3 | }; 4 | -------------------------------------------------------------------------------- /apps/blog/src/environments/environment.prod.ts: -------------------------------------------------------------------------------- 1 | export const environment = { 2 | production: true, 3 | }; 4 | -------------------------------------------------------------------------------- /apps/todos-api/src/environments/environment.ts: -------------------------------------------------------------------------------- 1 | export const environment = { 2 | production: false, 3 | }; 4 | -------------------------------------------------------------------------------- /apps/todos/src/environments/environment.prod.ts: -------------------------------------------------------------------------------- 1 | export const environment = { 2 | production: true, 3 | }; 4 | -------------------------------------------------------------------------------- /apps/todos/src/styles.css: -------------------------------------------------------------------------------- 1 | /* You can add global styles to this file, and also import other style files */ 2 | -------------------------------------------------------------------------------- /apps/blog-api/src/environments/environment.prod.ts: -------------------------------------------------------------------------------- 1 | export const environment = { 2 | production: true, 3 | }; 4 | -------------------------------------------------------------------------------- /apps/todos-api/src/environments/environment.prod.ts: -------------------------------------------------------------------------------- 1 | export const environment = { 2 | production: true, 3 | }; 4 | -------------------------------------------------------------------------------- /apps/blog/proxy.conf.json: -------------------------------------------------------------------------------- 1 | { 2 | "/api": { 3 | "target": "http://localhost:3333", 4 | "secure": false 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /apps/todos/proxy.conf.json: -------------------------------------------------------------------------------- 1 | { 2 | "/api": { 3 | "target": "http://localhost:3333", 4 | "secure": false 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /apps/todos-e2e/src/fixtures/example.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Using fixtures to represent data", 3 | "email": "hello@cypress.io" 4 | } 5 | -------------------------------------------------------------------------------- /apps/todos-e2e/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "files": [], 4 | "include": [], 5 | "references": [ 6 | { 7 | "path": "./tsconfig.e2e.json" 8 | } 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /libs/api-interfaces/README.md: -------------------------------------------------------------------------------- 1 | # api-interfaces 2 | 3 | This library was generated with [Nx](https://nx.dev). 4 | 5 | ## Running unit tests 6 | 7 | Run `nx test api-interfaces` to execute the unit tests via [Jest](https://jestjs.io). 8 | -------------------------------------------------------------------------------- /libs/api-interfaces/tsconfig.lib.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "types": [] 6 | }, 7 | "exclude": ["**/*.spec.ts"], 8 | "include": ["**/*.ts"] 9 | } 10 | -------------------------------------------------------------------------------- /apps/blog-api/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "types": ["node", "express"] 6 | }, 7 | "exclude": ["**/*.spec.ts"], 8 | "include": ["**/*.ts"] 9 | } 10 | -------------------------------------------------------------------------------- /apps/todos-api/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "types": ["node", "express"] 6 | }, 7 | "exclude": ["**/*.spec.ts"], 8 | "include": ["**/*.ts"] 9 | } 10 | -------------------------------------------------------------------------------- /apps/blog/src/polyfills.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Polyfill stable language features. These imports will be optimized by `@babel/preset-env`. 3 | * 4 | * See: https://github.com/zloirock/core-js#babel 5 | */ 6 | import 'core-js/stable'; 7 | import 'regenerator-runtime/runtime'; 8 | -------------------------------------------------------------------------------- /apps/todos/src/polyfills.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Polyfill stable language features. These imports will be optimized by `@babel/preset-env`. 3 | * 4 | * See: https://github.com/zloirock/core-js#babel 5 | */ 6 | import 'core-js/stable'; 7 | import 'regenerator-runtime/runtime'; 8 | -------------------------------------------------------------------------------- /apps/blog-api/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "module": "commonjs", 6 | "types": ["jest", "node"] 7 | }, 8 | "include": ["**/*.spec.ts", "**/*.d.ts"] 9 | } 10 | -------------------------------------------------------------------------------- /apps/todos-api/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "module": "commonjs", 6 | "types": ["jest", "node"] 7 | }, 8 | "include": ["**/*.spec.ts", "**/*.d.ts"] 9 | } 10 | -------------------------------------------------------------------------------- /apps/blog/src/environments/environment.ts: -------------------------------------------------------------------------------- 1 | // This file can be replaced during build by using the `fileReplacements` array. 2 | // When building for production, this file is replaced with `environment.prod.ts`. 3 | 4 | export const environment = { 5 | production: false, 6 | }; 7 | -------------------------------------------------------------------------------- /apps/blog/src/main.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | 4 | import App from './app/app'; 5 | 6 | ReactDOM.render( 7 | 8 | 9 | , 10 | document.getElementById('root') 11 | ); 12 | -------------------------------------------------------------------------------- /apps/todos/src/main.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | 4 | import App from './app/app'; 5 | 6 | ReactDOM.render( 7 | 8 | 9 | , 10 | document.getElementById('root') 11 | ); 12 | -------------------------------------------------------------------------------- /apps/todos/src/environments/environment.ts: -------------------------------------------------------------------------------- 1 | // This file can be replaced during build by using the `fileReplacements` array. 2 | // When building for production, this file is replaced with `environment.prod.ts`. 3 | 4 | export const environment = { 5 | production: false, 6 | }; 7 | -------------------------------------------------------------------------------- /apps/blog-api/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "files": [], 4 | "include": [], 5 | "references": [ 6 | { 7 | "path": "./tsconfig.app.json" 8 | }, 9 | { 10 | "path": "./tsconfig.spec.json" 11 | } 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /apps/todos-api/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "files": [], 4 | "include": [], 5 | "references": [ 6 | { 7 | "path": "./tsconfig.app.json" 8 | }, 9 | { 10 | "path": "./tsconfig.spec.json" 11 | } 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /libs/api-interfaces/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "files": [], 4 | "include": [], 5 | "references": [ 6 | { 7 | "path": "./tsconfig.lib.json" 8 | }, 9 | { 10 | "path": "./tsconfig.spec.json" 11 | } 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /apps/blog/babel-jest.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | [ 4 | "@babel/preset-env", 5 | { 6 | "targets": { 7 | "node": "current" 8 | } 9 | } 10 | ], 11 | "@babel/preset-typescript", 12 | "@babel/preset-react" 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /apps/todos/babel-jest.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | [ 4 | "@babel/preset-env", 5 | { 6 | "targets": { 7 | "node": "current" 8 | } 9 | } 10 | ], 11 | "@babel/preset-typescript", 12 | "@babel/preset-react" 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /apps/todos-e2e/tsconfig.e2e.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "sourceMap": false, 5 | "outDir": "../../dist/out-tsc", 6 | "allowJs": true, 7 | "types": ["cypress", "node"] 8 | }, 9 | "include": ["src/**/*.ts", "src/**/*.js"] 10 | } 11 | -------------------------------------------------------------------------------- /tools/tsconfig.tools.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.base.json", 3 | "compilerOptions": { 4 | "outDir": "../dist/out-tsc/tools", 5 | "rootDir": ".", 6 | "module": "commonjs", 7 | "target": "es5", 8 | "types": ["node"] 9 | }, 10 | "include": ["**/*.ts"] 11 | } 12 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | testMatch: ['**/+(*.)+(spec|test).+(ts|js)?(x)'], 3 | transform: { 4 | '^.+\\.(ts|js|html)$': 'ts-jest', 5 | }, 6 | resolver: '@nrwl/jest/plugins/resolver', 7 | moduleFileExtensions: ['ts', 'js', 'html'], 8 | coverageReporters: ['html'], 9 | }; 10 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # Editor configuration, see http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 2 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.md] 12 | max_line_length = off 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /apps/todos-e2e/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "rules": {}, 3 | "overrides": [ 4 | { 5 | "files": ["src/plugins/index.js"], 6 | "rules": { 7 | "@typescript-eslint/no-var-requires": "off", 8 | "no-undef": "off" 9 | } 10 | } 11 | ], 12 | "extends": ["plugin:cypress/recommended", "../../.eslintrc"], 13 | "ignorePatterns": ["!**/*"] 14 | } 15 | -------------------------------------------------------------------------------- /libs/api-interfaces/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "module": "commonjs", 6 | "types": ["jest", "node"] 7 | }, 8 | "include": [ 9 | "**/*.spec.ts", 10 | "**/*.spec.tsx", 11 | "**/*.spec.js", 12 | "**/*.spec.jsx", 13 | "**/*.d.ts" 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /apps/blog-api/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | name: 'blog-api', 3 | preset: '../../jest.config.js', 4 | globals: { 5 | 'ts-jest': { 6 | tsConfig: '/tsconfig.spec.json', 7 | }, 8 | }, 9 | transform: { 10 | '^.+\\.[tj]s$': 'ts-jest', 11 | }, 12 | moduleFileExtensions: ['ts', 'js', 'html'], 13 | coverageDirectory: '../../coverage/apps/blog-api', 14 | }; 15 | -------------------------------------------------------------------------------- /apps/blog/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | blog 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | -------------------------------------------------------------------------------- /apps/todos-api/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | name: 'todos-api', 3 | preset: '../../jest.config.js', 4 | globals: { 5 | 'ts-jest': { 6 | tsConfig: '/tsconfig.spec.json', 7 | }, 8 | }, 9 | transform: { 10 | '^.+\\.[tj]s$': 'ts-jest', 11 | }, 12 | moduleFileExtensions: ['ts', 'js', 'html'], 13 | coverageDirectory: '../../coverage/apps/todos-api', 14 | }; 15 | -------------------------------------------------------------------------------- /apps/todos/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Todos 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | -------------------------------------------------------------------------------- /apps/blog/src/app/star.svg: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /apps/todos/src/app/star.svg: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /libs/api-interfaces/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | name: 'api-interfaces', 3 | preset: '../../jest.config.js', 4 | globals: { 5 | 'ts-jest': { 6 | tsConfig: '/tsconfig.spec.json', 7 | }, 8 | }, 9 | transform: { 10 | '^.+\\.[tj]sx?$': 'ts-jest', 11 | }, 12 | moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'], 13 | coverageDirectory: '../../coverage/libs/api-interfaces', 14 | }; 15 | -------------------------------------------------------------------------------- /apps/blog/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "types": ["node"] 6 | }, 7 | "files": [ 8 | "../../node_modules/@nrwl/react/typings/cssmodule.d.ts", 9 | "../../node_modules/@nrwl/react/typings/image.d.ts" 10 | ], 11 | "exclude": ["**/*.spec.ts", "**/*.spec.tsx"], 12 | "include": ["**/*.js", "**/*.jsx", "**/*.ts", "**/*.tsx"] 13 | } 14 | -------------------------------------------------------------------------------- /apps/blog/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "compilerOptions": { 4 | "jsx": "react", 5 | "allowJs": true, 6 | "esModuleInterop": true, 7 | "allowSyntheticDefaultImports": true 8 | }, 9 | "files": [], 10 | "include": [], 11 | "references": [ 12 | { 13 | "path": "./tsconfig.app.json" 14 | }, 15 | { 16 | "path": "./tsconfig.spec.json" 17 | } 18 | ] 19 | } 20 | -------------------------------------------------------------------------------- /apps/todos/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "compilerOptions": { 4 | "jsx": "react", 5 | "allowJs": true, 6 | "esModuleInterop": true, 7 | "allowSyntheticDefaultImports": true 8 | }, 9 | "files": [], 10 | "include": [], 11 | "references": [ 12 | { 13 | "path": "./tsconfig.app.json" 14 | }, 15 | { 16 | "path": "./tsconfig.spec.json" 17 | } 18 | ] 19 | } 20 | -------------------------------------------------------------------------------- /apps/todos/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "types": ["node"] 6 | }, 7 | "files": [ 8 | "../../node_modules/@nrwl/react/typings/cssmodule.d.ts", 9 | "../../node_modules/@nrwl/react/typings/image.d.ts" 10 | ], 11 | "exclude": ["**/*.spec.ts", "**/*.spec.tsx"], 12 | "include": ["**/*.js", "**/*.jsx", "**/*.ts", "**/*.tsx"] 13 | } 14 | -------------------------------------------------------------------------------- /apps/blog/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | name: 'blog', 3 | preset: '../../jest.config.js', 4 | transform: { 5 | '^(?!.*\\.(js|jsx|ts|tsx|css|json)$)': '@nrwl/react/plugins/jest', 6 | '^.+\\.[tj]sx?$': [ 7 | 'babel-jest', 8 | { cwd: __dirname, configFile: './babel-jest.config.json' }, 9 | ], 10 | }, 11 | moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'], 12 | coverageDirectory: '../../coverage/apps/blog', 13 | }; 14 | -------------------------------------------------------------------------------- /apps/todos/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | name: 'todos', 3 | preset: '../../jest.config.js', 4 | transform: { 5 | '^(?!.*\\.(js|jsx|ts|tsx|css|json)$)': '@nrwl/react/plugins/jest', 6 | '^.+\\.[tj]sx?$': [ 7 | 'babel-jest', 8 | { cwd: __dirname, configFile: './babel-jest.config.json' }, 9 | ], 10 | }, 11 | moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'], 12 | coverageDirectory: '../../coverage/apps/todos', 13 | }; 14 | -------------------------------------------------------------------------------- /apps/todos-e2e/cypress.json: -------------------------------------------------------------------------------- 1 | { 2 | "fileServerFolder": ".", 3 | "fixturesFolder": "./src/fixtures", 4 | "integrationFolder": "./src/integration", 5 | "modifyObstructiveCode": false, 6 | "pluginsFile": "./src/plugins/index", 7 | "supportFile": "./src/support/index.ts", 8 | "video": true, 9 | "videosFolder": "../../dist/cypress/apps/todos-e2e/videos", 10 | "screenshotsFolder": "../../dist/cypress/apps/todos-e2e/screenshots", 11 | "chromeWebSecurity": false 12 | } 13 | -------------------------------------------------------------------------------- /apps/todos-e2e/src/integration/app.spec.ts: -------------------------------------------------------------------------------- 1 | import { getGreeting } from '../support/app.po'; 2 | 3 | describe('todos', () => { 4 | beforeEach(() => cy.visit('/')); 5 | 6 | it('should display welcome message', () => { 7 | // Custom command example, see `../support/commands.ts` file 8 | cy.login('my-email@something.com', 'myPassword'); 9 | 10 | // Function helper example, see `../support/app.po.ts` file 11 | getGreeting().contains('Welcome to todos!'); 12 | }); 13 | }); 14 | -------------------------------------------------------------------------------- /apps/blog-api/src/main.ts: -------------------------------------------------------------------------------- 1 | import * as express from 'express'; 2 | import { Message } from '@myorg/api-interfaces'; 3 | 4 | const app = express(); 5 | 6 | const greeting: Message = { message: 'Welcome to api!' }; 7 | 8 | app.get('/api', (req, res) => { 9 | res.send(greeting); 10 | }); 11 | 12 | const port = process.env.port || 3333; 13 | const server = app.listen(port, () => { 14 | console.log('Listening at http://localhost:' + port + '/api'); 15 | }); 16 | server.on('error', console.error); 17 | -------------------------------------------------------------------------------- /apps/todos-api/src/main.ts: -------------------------------------------------------------------------------- 1 | import * as express from 'express'; 2 | import { Message } from '@myorg/api-interfaces'; 3 | 4 | const app = express(); 5 | 6 | const greeting: Message = { message: 'Welcome to api!' }; 7 | 8 | app.get('/api', (req, res) => { 9 | res.send(greeting); 10 | }); 11 | 12 | const port = process.env.port || 3333; 13 | const server = app.listen(port, () => { 14 | console.log('Listening at http://localhost:' + port + '/api'); 15 | }); 16 | server.on('error', console.error); 17 | -------------------------------------------------------------------------------- /apps/blog/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "module": "commonjs", 6 | "types": ["jest", "node"] 7 | }, 8 | "include": [ 9 | "**/*.spec.ts", 10 | "**/*.spec.tsx", 11 | "**/*.spec.js", 12 | "**/*.spec.jsx", 13 | "**/*.d.ts" 14 | ], 15 | "files": [ 16 | "../../node_modules/@nrwl/react/typings/cssmodule.d.ts", 17 | "../../node_modules/@nrwl/react/typings/image.d.ts" 18 | ] 19 | } 20 | -------------------------------------------------------------------------------- /apps/todos/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "module": "commonjs", 6 | "types": ["jest", "node"] 7 | }, 8 | "include": [ 9 | "**/*.spec.ts", 10 | "**/*.spec.tsx", 11 | "**/*.spec.js", 12 | "**/*.spec.jsx", 13 | "**/*.d.ts" 14 | ], 15 | "files": [ 16 | "../../node_modules/@nrwl/react/typings/cssmodule.d.ts", 17 | "../../node_modules/@nrwl/react/typings/image.d.ts" 18 | ] 19 | } 20 | -------------------------------------------------------------------------------- /apps/blog/.browserslistrc: -------------------------------------------------------------------------------- 1 | # This file is used by: 2 | # 1. autoprefixer to adjust CSS to support the below specified browsers 3 | # 2. babel preset-env to adjust included polyfills 4 | # 5 | # For additional information regarding the format and rule options, please see: 6 | # https://github.com/browserslist/browserslist#queries 7 | # 8 | # If you need to support different browsers in production, you may tweak the list below. 9 | 10 | last 1 Chrome version 11 | last 1 Firefox version 12 | last 2 Edge major versions 13 | last 2 Safari major version 14 | last 2 iOS major versions 15 | Firefox ESR 16 | not IE 9-11 # For IE 9-11 support, remove 'not'. -------------------------------------------------------------------------------- /apps/todos/.browserslistrc: -------------------------------------------------------------------------------- 1 | # This file is used by: 2 | # 1. autoprefixer to adjust CSS to support the below specified browsers 3 | # 2. babel preset-env to adjust included polyfills 4 | # 5 | # For additional information regarding the format and rule options, please see: 6 | # https://github.com/browserslist/browserslist#queries 7 | # 8 | # If you need to support different browsers in production, you may tweak the list below. 9 | 10 | last 1 Chrome version 11 | last 1 Firefox version 12 | last 2 Edge major versions 13 | last 2 Safari major version 14 | last 2 iOS major versions 15 | Firefox ESR 16 | not IE 9-11 # For IE 9-11 support, remove 'not'. -------------------------------------------------------------------------------- /apps/blog/src/app/app.spec.tsx: -------------------------------------------------------------------------------- 1 | import App from "./app"; 2 | import React from "react"; 3 | import { 4 | cleanup, 5 | getByText, 6 | render, 7 | waitFor 8 | } from "@testing-library/react"; 9 | 10 | describe('App', () => { 11 | afterEach(() => { 12 | delete global['fetch']; 13 | cleanup(); 14 | }); 15 | 16 | it('should render successfully', async () => { 17 | global['fetch'] = jest.fn().mockResolvedValueOnce({ 18 | json: () => ({ 19 | message: 'my message', 20 | }), 21 | }); 22 | 23 | const { baseElement } = render(); 24 | await waitFor(() => getByText(baseElement, 'my message')); 25 | }); 26 | }); 27 | -------------------------------------------------------------------------------- /apps/todos/src/app/app.spec.tsx: -------------------------------------------------------------------------------- 1 | import App from "./app"; 2 | import React from "react"; 3 | import { 4 | cleanup, 5 | getByText, 6 | render, 7 | waitFor 8 | } from "@testing-library/react"; 9 | 10 | describe('App', () => { 11 | afterEach(() => { 12 | delete global['fetch']; 13 | cleanup(); 14 | }); 15 | 16 | it('should render successfully', async () => { 17 | global['fetch'] = jest.fn().mockResolvedValueOnce({ 18 | json: () => ({ 19 | message: 'my message', 20 | }), 21 | }); 22 | 23 | const { baseElement } = render(); 24 | await waitFor(() => getByText(baseElement, 'my message')); 25 | }); 26 | }); 27 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # compiled output 4 | /dist 5 | /tmp 6 | /out-tsc 7 | 8 | # dependencies 9 | /node_modules 10 | 11 | # IDEs and editors 12 | /.idea 13 | .project 14 | .classpath 15 | .c9/ 16 | *.launch 17 | .settings/ 18 | *.sublime-workspace 19 | 20 | # IDE - VSCode 21 | .vscode/* 22 | !.vscode/settings.json 23 | !.vscode/tasks.json 24 | !.vscode/launch.json 25 | !.vscode/extensions.json 26 | 27 | # misc 28 | /.sass-cache 29 | /connect.lock 30 | /coverage 31 | /libpeerconnection.log 32 | npm-debug.log 33 | yarn-error.log 34 | testem.log 35 | /typings 36 | 37 | # System Files 38 | .DS_Store 39 | Thumbs.db 40 | -------------------------------------------------------------------------------- /tsconfig.base.json: -------------------------------------------------------------------------------- 1 | { 2 | "compileOnSave": false, 3 | "compilerOptions": { 4 | "rootDir": ".", 5 | "sourceMap": true, 6 | "declaration": false, 7 | "moduleResolution": "node", 8 | "emitDecoratorMetadata": true, 9 | "experimentalDecorators": true, 10 | "importHelpers": true, 11 | "target": "es2015", 12 | "module": "esnext", 13 | "typeRoots": ["node_modules/@types"], 14 | "lib": ["es2017", "dom"], 15 | "skipLibCheck": true, 16 | "skipDefaultLibCheck": true, 17 | "baseUrl": ".", 18 | "paths": { 19 | "@myorg/api-interfaces": ["libs/api-interfaces/src/index.ts"] 20 | } 21 | }, 22 | "exclude": ["node_modules", "tmp"] 23 | } 24 | -------------------------------------------------------------------------------- /apps/todos-e2e/src/support/index.ts: -------------------------------------------------------------------------------- 1 | // *********************************************************** 2 | // This example support/index.js is processed and 3 | // loaded automatically before your test files. 4 | // 5 | // This is a great place to put global configuration and 6 | // behavior that modifies Cypress. 7 | // 8 | // You can change the location of this file or turn off 9 | // automatically serving support files with the 10 | // 'supportFile' configuration option. 11 | // 12 | // You can read more here: 13 | // https://on.cypress.io/configuration 14 | // *********************************************************** 15 | 16 | // Import commands.js using ES2015 syntax: 17 | import './commands'; 18 | -------------------------------------------------------------------------------- /.github/workflows/build-pr.yml: -------------------------------------------------------------------------------- 1 | on: 2 | pull_request: 3 | jobs: 4 | build: 5 | runs-on: ubuntu-latest 6 | steps: 7 | - uses: actions/checkout@v2 8 | with: 9 | fetch-depth: 0 10 | 11 | - uses: actions/setup-node@v2.1.0 12 | with: 13 | node-version: 12 14 | 15 | - run: yarn install --frozen-lockfile 16 | 17 | - run: yarn affected:lint --parallel --base=origin/${{ github.base_ref }} 18 | - run: yarn affected:test --parallel --base=origin/${{ github.base_ref }} 19 | - run: yarn affected:e2e --parallel --headless --base=origin/${{ github.base_ref }} 20 | 21 | - run: yarn affected:build --parallel --base=origin/${{ github.base_ref }} 22 | -------------------------------------------------------------------------------- /apps/blog/src/app/app.tsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useState } from "react"; 2 | import { Message } from "@myorg/api-interfaces"; 3 | 4 | export const App = () => { 5 | const [m, setMessage] = useState({ message: '' }); 6 | 7 | useEffect(() => { 8 | fetch('/api') 9 | .then((r) => r.json()) 10 | .then(setMessage); 11 | }, []); 12 | 13 | return ( 14 | <> 15 |
16 |

Welcome to blog!

17 | 21 |
22 |
{m.message}
23 | 24 | ); 25 | }; 26 | 27 | export default App; 28 | -------------------------------------------------------------------------------- /apps/todos/src/app/app.tsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useState } from 'react'; 2 | import { Message } from '@myorg/api-interfaces'; 3 | 4 | export const App = () => { 5 | const [m, setMessage] = useState({ message: '' }); 6 | 7 | useEffect(() => { 8 | fetch('/api') 9 | .then((r) => r.json()) 10 | .then(setMessage); 11 | }, []); 12 | 13 | return ( 14 | <> 15 |
16 |

Welcome to todos!

17 | 21 |
22 |
{m.message}
23 | 24 | ); 25 | }; 26 | 27 | export default App; 28 | -------------------------------------------------------------------------------- /externals/todos/tsconfig.base.json: -------------------------------------------------------------------------------- 1 | { 2 | "compileOnSave": false, 3 | "compilerOptions": { 4 | "rootDir": ".", 5 | "sourceMap": true, 6 | "declaration": false, 7 | "moduleResolution": "node", 8 | "emitDecoratorMetadata": true, 9 | "experimentalDecorators": true, 10 | "importHelpers": true, 11 | "target": "es2015", 12 | "module": "esnext", 13 | "typeRoots": [ 14 | "node_modules/@types" 15 | ], 16 | "lib": [ 17 | "es2017", 18 | "dom" 19 | ], 20 | "skipLibCheck": true, 21 | "skipDefaultLibCheck": true, 22 | "baseUrl": ".", 23 | "paths": { 24 | "@myorg/api-interfaces": [ 25 | "libs/api-interfaces/src/index.ts" 26 | ] 27 | } 28 | }, 29 | "exclude": [ 30 | "node_modules", 31 | "tmp" 32 | ] 33 | } -------------------------------------------------------------------------------- /.github/workflows/build-main.yml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | branches: 4 | - main 5 | 6 | jobs: 7 | build: 8 | name: Build & Release 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@v2 12 | with: 13 | fetch-depth: 0 14 | 15 | - uses: actions/setup-node@v2.1.0 16 | with: 17 | node-version: 12 18 | 19 | - run: yarn install --frozen-lockfile 20 | 21 | - run: yarn nx run-many --parallel --all --target=lint 22 | - run: yarn nx run-many --parallel --all --target=test --configuration=production 23 | - run: yarn nx run-many --parallel --all --target=e2e --headless --configuration=production 24 | 25 | - run: yarn affected:build --base=main~1 --parallel --configuration=production 26 | - run: yarn affected:release --base=main~1 --parallel --configuration=production 27 | -------------------------------------------------------------------------------- /apps/todos-e2e/src/plugins/index.js: -------------------------------------------------------------------------------- 1 | // *********************************************************** 2 | // This example plugins/index.js can be used to load plugins 3 | // 4 | // You can change the location of this file or turn off loading 5 | // the plugins file with the 'pluginsFile' configuration option. 6 | // 7 | // You can read more here: 8 | // https://on.cypress.io/plugins-guide 9 | // *********************************************************** 10 | 11 | // This function is called when a project is opened or re-opened (e.g. due to 12 | // the project's config changing) 13 | 14 | const { preprocessTypescript } = require('@nrwl/cypress/plugins/preprocessor'); 15 | 16 | module.exports = (on, config) => { 17 | // `on` is used to hook into various events Cypress emits 18 | // `config` is the resolved Cypress config 19 | 20 | // Preprocess Typescript file using Nx helper 21 | on('file:preprocessor', preprocessTypescript(config)); 22 | }; 23 | -------------------------------------------------------------------------------- /.github/workflows/move-code.yml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | pull_request_target: 4 | jobs: 5 | move-code: 6 | runs-on: ubuntu-latest 7 | steps: 8 | - uses: actions/checkout@v2 9 | with: 10 | fetch-depth: 0 11 | 12 | - uses: olivr/copybara-action@v1.2.2 13 | with: 14 | ssh_key: ${{ secrets.GH_SSH_BOT }} 15 | access_token: ${{ secrets.GH_TOKEN_BOT }} 16 | sot_repo: olivr/nx-copybara 17 | destination_repo: olivr/nx-copybara-todos 18 | push_include: '.github/workflows/build-pr.yml .github/workflows/move-code.yml apps/todos*/** libs/** externals/todos/** tools/** .*rc .*ignore *.json *.js *.lock' 19 | push_exclude: 'nx.json tsconfig.base.json workspace.json' 20 | pr_move: | 21 | nx.json||externals/todos/nx.json 22 | tsconfig.base.json||externals/todos/tsconfig.base.json 23 | workspace.json||externals/todos/workspace.json 24 | -------------------------------------------------------------------------------- /nx.json: -------------------------------------------------------------------------------- 1 | { 2 | "npmScope": "myorg", 3 | "affected": { 4 | "defaultBase": "main" 5 | }, 6 | "implicitDependencies": { 7 | "workspace.json": "*", 8 | "package.json": { 9 | "dependencies": "*", 10 | "devDependencies": "*" 11 | }, 12 | "tsconfig.base.json": "*", 13 | "tslint.json": "*", 14 | "nx.json": "*" 15 | }, 16 | "tasksRunnerOptions": { 17 | "default": { 18 | "runner": "@nrwl/workspace/tasks-runners/default", 19 | "options": { 20 | "cacheableOperations": ["build", "lint", "test", "e2e"] 21 | } 22 | } 23 | }, 24 | "projects": { 25 | "todos": { 26 | "tags": ["todos"] 27 | }, 28 | "todos-e2e": { 29 | "tags": ["todos"], 30 | "implicitDependencies": ["todos"] 31 | }, 32 | "todos-api": { 33 | "tags": ["todos"] 34 | }, 35 | "blog": { 36 | "tags": ["blog"] 37 | }, 38 | "blog-api": { 39 | "tags": ["blog"] 40 | }, 41 | "api-interfaces": { 42 | "tags": ["todos", "blog"] 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /externals/todos/nx.json: -------------------------------------------------------------------------------- 1 | { 2 | "npmScope": "myorg", 3 | "affected": { 4 | "defaultBase": "main" 5 | }, 6 | "implicitDependencies": { 7 | "workspace.json": "*", 8 | "package.json": { 9 | "dependencies": "*", 10 | "devDependencies": "*" 11 | }, 12 | "tsconfig.base.json": "*", 13 | "tslint.json": "*", 14 | "nx.json": "*" 15 | }, 16 | "tasksRunnerOptions": { 17 | "default": { 18 | "runner": "@nrwl/workspace/tasks-runners/default", 19 | "options": { 20 | "cacheableOperations": [ 21 | "build", 22 | "lint", 23 | "test", 24 | "e2e" 25 | ] 26 | } 27 | } 28 | }, 29 | "projects": { 30 | "todos": { 31 | "tags": [ 32 | "todos" 33 | ] 34 | }, 35 | "todos-e2e": { 36 | "tags": [ 37 | "todos" 38 | ], 39 | "implicitDependencies": [ 40 | "todos" 41 | ] 42 | }, 43 | "todos-api": { 44 | "tags": [ 45 | "todos" 46 | ] 47 | }, 48 | "api-interfaces": { 49 | "tags": [ 50 | "todos", 51 | "blog" 52 | ] 53 | } 54 | } 55 | } -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "root": true, 3 | "parser": "@typescript-eslint/parser", 4 | "parserOptions": { 5 | "ecmaVersion": 2018, 6 | "sourceType": "module", 7 | "project": "./tsconfig.*?.json" 8 | }, 9 | "ignorePatterns": ["**/*"], 10 | "plugins": ["@typescript-eslint", "@nrwl/nx"], 11 | "extends": [ 12 | "eslint:recommended", 13 | "plugin:@typescript-eslint/eslint-recommended", 14 | "plugin:@typescript-eslint/recommended", 15 | "prettier", 16 | "prettier/@typescript-eslint" 17 | ], 18 | "rules": { 19 | "@typescript-eslint/explicit-member-accessibility": "off", 20 | "@typescript-eslint/explicit-function-return-type": "off", 21 | "@typescript-eslint/no-parameter-properties": "off", 22 | "@nrwl/nx/enforce-module-boundaries": [ 23 | "error", 24 | { 25 | "enforceBuildableLibDependency": true, 26 | "allow": [], 27 | "depConstraints": [ 28 | { "sourceTag": "*", "onlyDependOnLibsWithTags": ["*"] } 29 | ] 30 | } 31 | ] 32 | }, 33 | "overrides": [ 34 | { 35 | "files": ["*.tsx"], 36 | "rules": { 37 | "@typescript-eslint/no-unused-vars": "off" 38 | } 39 | } 40 | ] 41 | } 42 | -------------------------------------------------------------------------------- /apps/todos-e2e/src/support/commands.ts: -------------------------------------------------------------------------------- 1 | // *********************************************** 2 | // This example commands.js shows you how to 3 | // create various custom commands and overwrite 4 | // existing commands. 5 | // 6 | // For more comprehensive examples of custom 7 | // commands please read more here: 8 | // https://on.cypress.io/custom-commands 9 | // *********************************************** 10 | // eslint-disable-next-line @typescript-eslint/no-namespace 11 | declare namespace Cypress { 12 | interface Chainable { 13 | login(email: string, password: string): void; 14 | } 15 | } 16 | // 17 | // -- This is a parent command -- 18 | Cypress.Commands.add('login', (email, password) => { 19 | console.log('Custom command example: Login', email, password); 20 | }); 21 | // 22 | // -- This is a child command -- 23 | // Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... }) 24 | // 25 | // 26 | // -- This is a dual command -- 27 | // Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... }) 28 | // 29 | // 30 | // -- This will overwrite an existing command -- 31 | // Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... }) 32 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Open source NX sub-project as a new repo with Copybara and Github Actions 2 | 3 | This repo is an example [Nx](https://nx.dev) monorepo to demonstrate how to use [Copybara Action](https://github.com/olivr/copybara-action/) to open-source a part of the monorepo. Pull-Requests in the destination repo will be synced back to your main repo. 4 | 5 | ```text 6 | Source of Truth Destination 7 | 8 | +---------------+ Copybara +---------------+ 9 | | Branch +------------> | Branch | 10 | +-------+-------+ +---------------+ 11 | ^ 12 | | 13 | | 14 | +-------+-------+ Copybara +---------------+ 15 | | Pull Requests | <------------+ Pull Requests | 16 | +---------------+ +---------------+ 17 | ``` 18 | 19 | ## How it works 20 | 21 | 1. Apps and libs are tagged properly 22 | 2. Running `node tools/externals/prepare.js todos` will update `externals/todos`. (The output of this tool must be kept up to date and committed, you could set-up a pre-commit hook) 23 | 3. The Github workflow `.github/workflows/move-code.yml` will then take care of the rest. 24 | 25 | ## Try it! 26 | 27 | 1. Fork this repo 28 | 2. Create another empty repo to use as the destination 29 | 3. [Configure the secrets](https://github.com/olivr/copybara-action/blob/main/docs/basic-usage.md) 30 | 4. Run `node tools/externals/prepare.js blog` on your fork, you will see the new folder `externals/blog` 31 | 5. Change `.github/workflows/move-code.yml` accordingly (basically search/replace _todos_ by _blog_) and adjust the sot/destination repo values. 32 | 33 | ## Use in your own repo 34 | 35 | The two important bits that you need to copy in your own repo are [prepare.js](/tools/externals/prepare.js) and the Github [workflow](.github/workflows/move-code.yml). Check out [Copybara Action](https://github.com/olivr/copybara-action) for more customization. 36 | -------------------------------------------------------------------------------- /tools/externals/prepare.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | 4 | const rootDir = process.env.PWD; 5 | const extDir = path.join(rootDir, 'externals'); 6 | 7 | const nxSource = JSON.parse( 8 | fs.readFileSync(path.join(rootDir, 'nx.json'), 'utf-8') 9 | ); 10 | const wsSource = JSON.parse( 11 | fs.readFileSync(path.join(rootDir, 'workspace.json'), 'utf-8') 12 | ); 13 | const tsSource = JSON.parse( 14 | fs.readFileSync(path.join(rootDir, 'tsconfig.base.json'), 'utf-8') 15 | ); 16 | 17 | const externals = process.argv.slice(2); 18 | //const externals = nxSource.externals 19 | 20 | if (externals.length && !fs.existsSync(extDir)) fs.mkdirSync(extDir); 21 | 22 | externals.forEach((tag) => { 23 | const nx = { ...nxSource }; 24 | const ws = { ...wsSource }; 25 | const ts = { ...tsSource }; 26 | const projects = {}; 27 | 28 | // Determine projects to include 29 | Object.entries(nx.projects).forEach(([k, v]) => { 30 | if (v.tags.includes(tag)) projects[k] = ''; 31 | }); 32 | 33 | // Prepare nx.json 34 | nx.projects = Object.keys(nx.projects) 35 | .filter((key) => Object.keys(projects).includes(key)) 36 | .reduce((obj, key) => { 37 | obj[key] = nx.projects[key]; 38 | return obj; 39 | }, {}); 40 | 41 | // Prepare workspace.json 42 | ws.projects = Object.keys(ws.projects) 43 | .filter((key) => Object.keys(projects).includes(key)) 44 | .reduce((obj, key) => { 45 | obj[key] = ws.projects[key]; 46 | projects[key] = ws.projects[key].root.replace(/\/$/, '').concat('/'); 47 | return obj; 48 | }, {}); 49 | 50 | // Prepare tsconfig.base.json 51 | const paths = new RegExp(`^(${Object.values(projects).join('|')})`); 52 | ts.compilerOptions.paths = Object.entries(ts.compilerOptions.paths) 53 | .filter(([k, v]) => v.filter((path) => paths.test(path)).length == v.length) 54 | .reduce((obj, [k, v]) => { 55 | obj[k] = ts.compilerOptions.paths[k]; 56 | return obj; 57 | }, {}); 58 | 59 | // Save files 60 | const dir = path.join(extDir, tag); 61 | if (!fs.existsSync(dir)) fs.mkdirSync(dir); 62 | fs.writeFileSync(path.join(dir, 'nx.json'), JSON.stringify(nx, null, 2)); 63 | fs.writeFileSync( 64 | path.join(dir, 'workspace.json'), 65 | JSON.stringify(ws, null, 2) 66 | ); 67 | fs.writeFileSync( 68 | path.join(dir, 'tsconfig.base.json'), 69 | JSON.stringify(ts, null, 2) 70 | ); 71 | }); 72 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "myorg", 3 | "version": "0.0.0", 4 | "license": "MIT", 5 | "scripts": { 6 | "nx": "nx", 7 | "start": "nx serve", 8 | "build": "nx build", 9 | "test": "nx test", 10 | "lint": "nx workspace-lint && nx lint", 11 | "e2e": "nx e2e", 12 | "affected:apps": "nx affected:apps", 13 | "affected:libs": "nx affected:libs", 14 | "affected:build": "nx affected:build", 15 | "affected:e2e": "nx affected:e2e", 16 | "affected:test": "nx affected:test", 17 | "affected:lint": "nx affected:lint", 18 | "affected:release": "nx affected --target=release", 19 | "affected:dep-graph": "nx affected:dep-graph", 20 | "affected": "nx affected", 21 | "format": "nx format:write", 22 | "format:write": "nx format:write", 23 | "format:check": "nx format:check", 24 | "update": "nx migrate latest", 25 | "workspace-schematic": "nx workspace-schematic", 26 | "dep-graph": "nx dep-graph", 27 | "help": "nx help" 28 | }, 29 | "private": true, 30 | "dependencies": { 31 | "document-register-element": "1.13.1", 32 | "react": "16.13.1", 33 | "react-dom": "16.13.1", 34 | "express": "4.17.1" 35 | }, 36 | "devDependencies": { 37 | "@nrwl/workspace": "10.2.1", 38 | "@types/node": "~8.9.4", 39 | "dotenv": "6.2.0", 40 | "ts-node": "~7.0.0", 41 | "tslint": "~6.0.0", 42 | "eslint": "6.8.0", 43 | "typescript": "~3.9.3", 44 | "prettier": "2.0.4", 45 | "@nrwl/react": "10.2.1", 46 | "@nrwl/express": "10.2.1", 47 | "@nrwl/jest": "10.2.1", 48 | "jest": "26.2.2", 49 | "@types/jest": "26.0.8", 50 | "ts-jest": "26.1.4", 51 | "cypress": "^4.1.0", 52 | "@nrwl/cypress": "10.2.1", 53 | "@nrwl/web": "10.2.1", 54 | "@types/react": "16.9.38", 55 | "@types/react-dom": "16.9.8", 56 | "@testing-library/react": "10.4.1", 57 | "@nrwl/eslint-plugin-nx": "10.2.1", 58 | "@typescript-eslint/parser": "2.19.2", 59 | "@typescript-eslint/eslint-plugin": "2.19.2", 60 | "eslint-config-prettier": "6.0.0", 61 | "eslint-plugin-import": "2.21.2", 62 | "eslint-plugin-jsx-a11y": "6.3.1", 63 | "eslint-plugin-react": "7.20.0", 64 | "eslint-plugin-react-hooks": "4.0.4", 65 | "eslint-plugin-cypress": "^2.10.3", 66 | "@babel/core": "7.9.6", 67 | "@babel/preset-env": "7.9.6", 68 | "@babel/preset-typescript": "7.9.0", 69 | "@babel/preset-react": "7.9.4", 70 | "babel-jest": "26.2.2", 71 | "@nrwl/node": "10.2.1", 72 | "@types/express": "4.17.0" 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /apps/blog/src/app/app.css: -------------------------------------------------------------------------------- 1 | .app { 2 | font-family: sans-serif; 3 | min-width: 300px; 4 | max-width: 600px; 5 | margin: 50px auto; 6 | } 7 | 8 | .app .gutter-left { 9 | margin-left: 9px; 10 | } 11 | 12 | .app .col-span-2 { 13 | grid-column: span 2; 14 | } 15 | 16 | .app .flex { 17 | display: flex; 18 | align-items: center; 19 | justify-content: center; 20 | } 21 | 22 | .app header { 23 | background-color: #143055; 24 | color: white; 25 | padding: 5px; 26 | border-radius: 3px; 27 | } 28 | 29 | .app main { 30 | padding: 0 36px; 31 | } 32 | 33 | .app p { 34 | text-align: center; 35 | } 36 | 37 | .app h1 { 38 | text-align: center; 39 | margin-left: 18px; 40 | font-size: 24px; 41 | } 42 | 43 | .app h2 { 44 | text-align: center; 45 | font-size: 20px; 46 | margin: 40px 0 10px 0; 47 | } 48 | 49 | .app .resources { 50 | text-align: center; 51 | list-style: none; 52 | padding: 0; 53 | display: grid; 54 | grid-gap: 9px; 55 | grid-template-columns: 1fr 1fr; 56 | } 57 | 58 | .app .resource { 59 | color: #0094ba; 60 | height: 36px; 61 | background-color: rgba(0, 0, 0, 0); 62 | border: 1px solid rgba(0, 0, 0, 0.12); 63 | border-radius: 4px; 64 | padding: 3px 9px; 65 | text-decoration: none; 66 | } 67 | 68 | .app .resource:hover { 69 | background-color: rgba(68, 138, 255, 0.04); 70 | } 71 | 72 | .app pre { 73 | padding: 9px; 74 | border-radius: 4px; 75 | background-color: black; 76 | color: #eee; 77 | } 78 | 79 | .app details { 80 | border-radius: 4px; 81 | color: #333; 82 | background-color: rgba(0, 0, 0, 0); 83 | border: 1px solid rgba(0, 0, 0, 0.12); 84 | padding: 3px 9px; 85 | margin-bottom: 9px; 86 | } 87 | 88 | .app summary { 89 | outline: none; 90 | height: 36px; 91 | line-height: 36px; 92 | } 93 | 94 | .app .github-star-container { 95 | margin-top: 12px; 96 | line-height: 20px; 97 | } 98 | 99 | .app .github-star-container a { 100 | display: flex; 101 | align-items: center; 102 | text-decoration: none; 103 | color: #333; 104 | } 105 | 106 | .app .github-star-badge { 107 | color: #24292e; 108 | display: flex; 109 | align-items: center; 110 | font-size: 12px; 111 | padding: 3px 10px; 112 | border: 1px solid rgba(27, 31, 35, 0.2); 113 | border-radius: 3px; 114 | background-image: linear-gradient(-180deg, #fafbfc, #eff3f6 90%); 115 | margin-left: 4px; 116 | font-weight: 600; 117 | } 118 | 119 | .app .github-star-badge:hover { 120 | background-image: linear-gradient(-180deg, #f0f3f6, #e6ebf1 90%); 121 | border-color: rgba(27, 31, 35, 0.35); 122 | background-position: -0.5em; 123 | } 124 | .app .github-star-badge .material-icons { 125 | height: 16px; 126 | width: 16px; 127 | margin-right: 4px; 128 | } 129 | -------------------------------------------------------------------------------- /apps/todos/src/app/app.css: -------------------------------------------------------------------------------- 1 | .app { 2 | font-family: sans-serif; 3 | min-width: 300px; 4 | max-width: 600px; 5 | margin: 50px auto; 6 | } 7 | 8 | .app .gutter-left { 9 | margin-left: 9px; 10 | } 11 | 12 | .app .col-span-2 { 13 | grid-column: span 2; 14 | } 15 | 16 | .app .flex { 17 | display: flex; 18 | align-items: center; 19 | justify-content: center; 20 | } 21 | 22 | .app header { 23 | background-color: #143055; 24 | color: white; 25 | padding: 5px; 26 | border-radius: 3px; 27 | } 28 | 29 | .app main { 30 | padding: 0 36px; 31 | } 32 | 33 | .app p { 34 | text-align: center; 35 | } 36 | 37 | .app h1 { 38 | text-align: center; 39 | margin-left: 18px; 40 | font-size: 24px; 41 | } 42 | 43 | .app h2 { 44 | text-align: center; 45 | font-size: 20px; 46 | margin: 40px 0 10px 0; 47 | } 48 | 49 | .app .resources { 50 | text-align: center; 51 | list-style: none; 52 | padding: 0; 53 | display: grid; 54 | grid-gap: 9px; 55 | grid-template-columns: 1fr 1fr; 56 | } 57 | 58 | .app .resource { 59 | color: #0094ba; 60 | height: 36px; 61 | background-color: rgba(0, 0, 0, 0); 62 | border: 1px solid rgba(0, 0, 0, 0.12); 63 | border-radius: 4px; 64 | padding: 3px 9px; 65 | text-decoration: none; 66 | } 67 | 68 | .app .resource:hover { 69 | background-color: rgba(68, 138, 255, 0.04); 70 | } 71 | 72 | .app pre { 73 | padding: 9px; 74 | border-radius: 4px; 75 | background-color: black; 76 | color: #eee; 77 | } 78 | 79 | .app details { 80 | border-radius: 4px; 81 | color: #333; 82 | background-color: rgba(0, 0, 0, 0); 83 | border: 1px solid rgba(0, 0, 0, 0.12); 84 | padding: 3px 9px; 85 | margin-bottom: 9px; 86 | } 87 | 88 | .app summary { 89 | outline: none; 90 | height: 36px; 91 | line-height: 36px; 92 | } 93 | 94 | .app .github-star-container { 95 | margin-top: 12px; 96 | line-height: 20px; 97 | } 98 | 99 | .app .github-star-container a { 100 | display: flex; 101 | align-items: center; 102 | text-decoration: none; 103 | color: #333; 104 | } 105 | 106 | .app .github-star-badge { 107 | color: #24292e; 108 | display: flex; 109 | align-items: center; 110 | font-size: 12px; 111 | padding: 3px 10px; 112 | border: 1px solid rgba(27, 31, 35, 0.2); 113 | border-radius: 3px; 114 | background-image: linear-gradient(-180deg, #fafbfc, #eff3f6 90%); 115 | margin-left: 4px; 116 | font-weight: 600; 117 | } 118 | 119 | .app .github-star-badge:hover { 120 | background-image: linear-gradient(-180deg, #f0f3f6, #e6ebf1 90%); 121 | border-color: rgba(27, 31, 35, 0.35); 122 | background-position: -0.5em; 123 | } 124 | .app .github-star-badge .material-icons { 125 | height: 16px; 126 | width: 16px; 127 | margin-right: 4px; 128 | } 129 | -------------------------------------------------------------------------------- /apps/blog/src/app/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /apps/todos/src/app/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /apps/blog/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | "array-callback-return": "warn", 4 | "dot-location": ["warn", "property"], 5 | "eqeqeq": ["warn", "smart"], 6 | "new-parens": "warn", 7 | "no-caller": "warn", 8 | "no-cond-assign": ["warn", "except-parens"], 9 | "no-const-assign": "warn", 10 | "no-control-regex": "warn", 11 | "no-delete-var": "warn", 12 | "no-dupe-args": "warn", 13 | "no-dupe-keys": "warn", 14 | "no-duplicate-case": "warn", 15 | "no-empty-character-class": "warn", 16 | "no-empty-pattern": "warn", 17 | "no-eval": "warn", 18 | "no-ex-assign": "warn", 19 | "no-extend-native": "warn", 20 | "no-extra-bind": "warn", 21 | "no-extra-label": "warn", 22 | "no-fallthrough": "warn", 23 | "no-func-assign": "warn", 24 | "no-implied-eval": "warn", 25 | "no-invalid-regexp": "warn", 26 | "no-iterator": "warn", 27 | "no-label-var": "warn", 28 | "no-labels": ["warn", { "allowLoop": true, "allowSwitch": false }], 29 | "no-lone-blocks": "warn", 30 | "no-loop-func": "warn", 31 | "no-mixed-operators": [ 32 | "warn", 33 | { 34 | "groups": [ 35 | ["&", "|", "^", "~", "<<", ">>", ">>>"], 36 | ["==", "!=", "===", "!==", ">", ">=", "<", "<="], 37 | ["&&", "||"], 38 | ["in", "instanceof"] 39 | ], 40 | "allowSamePrecedence": false 41 | } 42 | ], 43 | "no-multi-str": "warn", 44 | "no-native-reassign": "warn", 45 | "no-negated-in-lhs": "warn", 46 | "no-new-func": "warn", 47 | "no-new-object": "warn", 48 | "no-new-symbol": "warn", 49 | "no-new-wrappers": "warn", 50 | "no-obj-calls": "warn", 51 | "no-octal": "warn", 52 | "no-octal-escape": "warn", 53 | "no-redeclare": "warn", 54 | "no-regex-spaces": "warn", 55 | "no-restricted-syntax": ["warn", "WithStatement"], 56 | "no-script-url": "warn", 57 | "no-self-assign": "warn", 58 | "no-self-compare": "warn", 59 | "no-sequences": "warn", 60 | "no-shadow-restricted-names": "warn", 61 | "no-sparse-arrays": "warn", 62 | "no-template-curly-in-string": "warn", 63 | "no-this-before-super": "warn", 64 | "no-throw-literal": "warn", 65 | "no-restricted-globals": [ 66 | "error", 67 | "addEventListener", 68 | "blur", 69 | "close", 70 | "closed", 71 | "confirm", 72 | "defaultStatus", 73 | "defaultstatus", 74 | "event", 75 | "external", 76 | "find", 77 | "focus", 78 | "frameElement", 79 | "frames", 80 | "history", 81 | "innerHeight", 82 | "innerWidth", 83 | "length", 84 | "location", 85 | "locationbar", 86 | "menubar", 87 | "moveBy", 88 | "moveTo", 89 | "name", 90 | "onblur", 91 | "onerror", 92 | "onfocus", 93 | "onload", 94 | "onresize", 95 | "onunload", 96 | "open", 97 | "opener", 98 | "opera", 99 | "outerHeight", 100 | "outerWidth", 101 | "pageXOffset", 102 | "pageYOffset", 103 | "parent", 104 | "print", 105 | "removeEventListener", 106 | "resizeBy", 107 | "resizeTo", 108 | "screen", 109 | "screenLeft", 110 | "screenTop", 111 | "screenX", 112 | "screenY", 113 | "scroll", 114 | "scrollbars", 115 | "scrollBy", 116 | "scrollTo", 117 | "scrollX", 118 | "scrollY", 119 | "self", 120 | "status", 121 | "statusbar", 122 | "stop", 123 | "toolbar", 124 | "top" 125 | ], 126 | "no-unexpected-multiline": "warn", 127 | "no-unreachable": "warn", 128 | "no-unused-expressions": "off", 129 | "no-unused-labels": "warn", 130 | "no-useless-computed-key": "warn", 131 | "no-useless-concat": "warn", 132 | "no-useless-escape": "warn", 133 | "no-useless-rename": [ 134 | "warn", 135 | { 136 | "ignoreDestructuring": false, 137 | "ignoreImport": false, 138 | "ignoreExport": false 139 | } 140 | ], 141 | "no-with": "warn", 142 | "no-whitespace-before-property": "warn", 143 | "react-hooks/exhaustive-deps": "warn", 144 | "require-yield": "warn", 145 | "rest-spread-spacing": ["warn", "never"], 146 | "strict": ["warn", "never"], 147 | "unicode-bom": ["warn", "never"], 148 | "use-isnan": "warn", 149 | "valid-typeof": "warn", 150 | "no-restricted-properties": [ 151 | "error", 152 | { 153 | "object": "require", 154 | "property": "ensure", 155 | "message": "Please use import() instead. More info: https://facebook.github.io/create-react-app/docs/code-splitting" 156 | }, 157 | { 158 | "object": "System", 159 | "property": "import", 160 | "message": "Please use import() instead. More info: https://facebook.github.io/create-react-app/docs/code-splitting" 161 | } 162 | ], 163 | "getter-return": "warn", 164 | "import/first": "error", 165 | "import/no-amd": "error", 166 | "import/no-webpack-loader-syntax": "error", 167 | "react/forbid-foreign-prop-types": ["warn", { "allowInPropTypes": true }], 168 | "react/jsx-no-comment-textnodes": "warn", 169 | "react/jsx-no-duplicate-props": "warn", 170 | "react/jsx-no-target-blank": "warn", 171 | "react/jsx-no-undef": "error", 172 | "react/jsx-pascal-case": ["warn", { "allowAllCaps": true, "ignore": [] }], 173 | "react/jsx-uses-react": "warn", 174 | "react/jsx-uses-vars": "warn", 175 | "react/no-danger-with-children": "warn", 176 | "react/no-direct-mutation-state": "warn", 177 | "react/no-is-mounted": "warn", 178 | "react/no-typos": "error", 179 | "react/react-in-jsx-scope": "error", 180 | "react/require-render-return": "error", 181 | "react/style-prop-object": "warn", 182 | "react/jsx-no-useless-fragment": "warn", 183 | "jsx-a11y/accessible-emoji": "warn", 184 | "jsx-a11y/alt-text": "warn", 185 | "jsx-a11y/anchor-has-content": "warn", 186 | "jsx-a11y/anchor-is-valid": [ 187 | "warn", 188 | { "aspects": ["noHref", "invalidHref"] } 189 | ], 190 | "jsx-a11y/aria-activedescendant-has-tabindex": "warn", 191 | "jsx-a11y/aria-props": "warn", 192 | "jsx-a11y/aria-proptypes": "warn", 193 | "jsx-a11y/aria-role": "warn", 194 | "jsx-a11y/aria-unsupported-elements": "warn", 195 | "jsx-a11y/heading-has-content": "warn", 196 | "jsx-a11y/iframe-has-title": "warn", 197 | "jsx-a11y/img-redundant-alt": "warn", 198 | "jsx-a11y/no-access-key": "warn", 199 | "jsx-a11y/no-distracting-elements": "warn", 200 | "jsx-a11y/no-redundant-roles": "warn", 201 | "jsx-a11y/role-has-required-aria-props": "warn", 202 | "jsx-a11y/role-supports-aria-props": "warn", 203 | "jsx-a11y/scope": "warn", 204 | "react-hooks/rules-of-hooks": "error", 205 | "default-case": "off", 206 | "no-dupe-class-members": "off", 207 | "no-undef": "off", 208 | "@typescript-eslint/consistent-type-assertions": "warn", 209 | "no-array-constructor": "off", 210 | "@typescript-eslint/no-array-constructor": "warn", 211 | "@typescript-eslint/no-namespace": "error", 212 | "no-use-before-define": "off", 213 | "@typescript-eslint/no-use-before-define": [ 214 | "warn", 215 | { 216 | "functions": false, 217 | "classes": false, 218 | "variables": false, 219 | "typedefs": false 220 | } 221 | ], 222 | "no-unused-vars": "off", 223 | "@typescript-eslint/no-unused-vars": [ 224 | "warn", 225 | { "args": "none", "ignoreRestSiblings": true } 226 | ], 227 | "no-useless-constructor": "off", 228 | "@typescript-eslint/no-useless-constructor": "warn", 229 | "@typescript-eslint/no-unused-expressions": [ 230 | "error", 231 | { 232 | "allowShortCircuit": true, 233 | "allowTernary": true, 234 | "allowTaggedTemplates": true 235 | } 236 | ] 237 | }, 238 | "env": { 239 | "browser": true, 240 | "commonjs": true, 241 | "es6": true, 242 | "jest": true, 243 | "node": true 244 | }, 245 | "settings": { "react": { "version": "detect" } }, 246 | "plugins": ["import", "jsx-a11y", "react", "react-hooks"], 247 | "extends": ["../../.eslintrc"], 248 | "ignorePatterns": ["!**/*"] 249 | } 250 | -------------------------------------------------------------------------------- /apps/todos/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | "array-callback-return": "warn", 4 | "dot-location": ["warn", "property"], 5 | "eqeqeq": ["warn", "smart"], 6 | "new-parens": "warn", 7 | "no-caller": "warn", 8 | "no-cond-assign": ["warn", "except-parens"], 9 | "no-const-assign": "warn", 10 | "no-control-regex": "warn", 11 | "no-delete-var": "warn", 12 | "no-dupe-args": "warn", 13 | "no-dupe-keys": "warn", 14 | "no-duplicate-case": "warn", 15 | "no-empty-character-class": "warn", 16 | "no-empty-pattern": "warn", 17 | "no-eval": "warn", 18 | "no-ex-assign": "warn", 19 | "no-extend-native": "warn", 20 | "no-extra-bind": "warn", 21 | "no-extra-label": "warn", 22 | "no-fallthrough": "warn", 23 | "no-func-assign": "warn", 24 | "no-implied-eval": "warn", 25 | "no-invalid-regexp": "warn", 26 | "no-iterator": "warn", 27 | "no-label-var": "warn", 28 | "no-labels": ["warn", { "allowLoop": true, "allowSwitch": false }], 29 | "no-lone-blocks": "warn", 30 | "no-loop-func": "warn", 31 | "no-mixed-operators": [ 32 | "warn", 33 | { 34 | "groups": [ 35 | ["&", "|", "^", "~", "<<", ">>", ">>>"], 36 | ["==", "!=", "===", "!==", ">", ">=", "<", "<="], 37 | ["&&", "||"], 38 | ["in", "instanceof"] 39 | ], 40 | "allowSamePrecedence": false 41 | } 42 | ], 43 | "no-multi-str": "warn", 44 | "no-native-reassign": "warn", 45 | "no-negated-in-lhs": "warn", 46 | "no-new-func": "warn", 47 | "no-new-object": "warn", 48 | "no-new-symbol": "warn", 49 | "no-new-wrappers": "warn", 50 | "no-obj-calls": "warn", 51 | "no-octal": "warn", 52 | "no-octal-escape": "warn", 53 | "no-redeclare": "warn", 54 | "no-regex-spaces": "warn", 55 | "no-restricted-syntax": ["warn", "WithStatement"], 56 | "no-script-url": "warn", 57 | "no-self-assign": "warn", 58 | "no-self-compare": "warn", 59 | "no-sequences": "warn", 60 | "no-shadow-restricted-names": "warn", 61 | "no-sparse-arrays": "warn", 62 | "no-template-curly-in-string": "warn", 63 | "no-this-before-super": "warn", 64 | "no-throw-literal": "warn", 65 | "no-restricted-globals": [ 66 | "error", 67 | "addEventListener", 68 | "blur", 69 | "close", 70 | "closed", 71 | "confirm", 72 | "defaultStatus", 73 | "defaultstatus", 74 | "event", 75 | "external", 76 | "find", 77 | "focus", 78 | "frameElement", 79 | "frames", 80 | "history", 81 | "innerHeight", 82 | "innerWidth", 83 | "length", 84 | "location", 85 | "locationbar", 86 | "menubar", 87 | "moveBy", 88 | "moveTo", 89 | "name", 90 | "onblur", 91 | "onerror", 92 | "onfocus", 93 | "onload", 94 | "onresize", 95 | "onunload", 96 | "open", 97 | "opener", 98 | "opera", 99 | "outerHeight", 100 | "outerWidth", 101 | "pageXOffset", 102 | "pageYOffset", 103 | "parent", 104 | "print", 105 | "removeEventListener", 106 | "resizeBy", 107 | "resizeTo", 108 | "screen", 109 | "screenLeft", 110 | "screenTop", 111 | "screenX", 112 | "screenY", 113 | "scroll", 114 | "scrollbars", 115 | "scrollBy", 116 | "scrollTo", 117 | "scrollX", 118 | "scrollY", 119 | "self", 120 | "status", 121 | "statusbar", 122 | "stop", 123 | "toolbar", 124 | "top" 125 | ], 126 | "no-unexpected-multiline": "warn", 127 | "no-unreachable": "warn", 128 | "no-unused-expressions": "off", 129 | "no-unused-labels": "warn", 130 | "no-useless-computed-key": "warn", 131 | "no-useless-concat": "warn", 132 | "no-useless-escape": "warn", 133 | "no-useless-rename": [ 134 | "warn", 135 | { 136 | "ignoreDestructuring": false, 137 | "ignoreImport": false, 138 | "ignoreExport": false 139 | } 140 | ], 141 | "no-with": "warn", 142 | "no-whitespace-before-property": "warn", 143 | "react-hooks/exhaustive-deps": "warn", 144 | "require-yield": "warn", 145 | "rest-spread-spacing": ["warn", "never"], 146 | "strict": ["warn", "never"], 147 | "unicode-bom": ["warn", "never"], 148 | "use-isnan": "warn", 149 | "valid-typeof": "warn", 150 | "no-restricted-properties": [ 151 | "error", 152 | { 153 | "object": "require", 154 | "property": "ensure", 155 | "message": "Please use import() instead. More info: https://facebook.github.io/create-react-app/docs/code-splitting" 156 | }, 157 | { 158 | "object": "System", 159 | "property": "import", 160 | "message": "Please use import() instead. More info: https://facebook.github.io/create-react-app/docs/code-splitting" 161 | } 162 | ], 163 | "getter-return": "warn", 164 | "import/first": "error", 165 | "import/no-amd": "error", 166 | "import/no-webpack-loader-syntax": "error", 167 | "react/forbid-foreign-prop-types": ["warn", { "allowInPropTypes": true }], 168 | "react/jsx-no-comment-textnodes": "warn", 169 | "react/jsx-no-duplicate-props": "warn", 170 | "react/jsx-no-target-blank": "warn", 171 | "react/jsx-no-undef": "error", 172 | "react/jsx-pascal-case": ["warn", { "allowAllCaps": true, "ignore": [] }], 173 | "react/jsx-uses-react": "warn", 174 | "react/jsx-uses-vars": "warn", 175 | "react/no-danger-with-children": "warn", 176 | "react/no-direct-mutation-state": "warn", 177 | "react/no-is-mounted": "warn", 178 | "react/no-typos": "error", 179 | "react/react-in-jsx-scope": "error", 180 | "react/require-render-return": "error", 181 | "react/style-prop-object": "warn", 182 | "react/jsx-no-useless-fragment": "warn", 183 | "jsx-a11y/accessible-emoji": "warn", 184 | "jsx-a11y/alt-text": "warn", 185 | "jsx-a11y/anchor-has-content": "warn", 186 | "jsx-a11y/anchor-is-valid": [ 187 | "warn", 188 | { "aspects": ["noHref", "invalidHref"] } 189 | ], 190 | "jsx-a11y/aria-activedescendant-has-tabindex": "warn", 191 | "jsx-a11y/aria-props": "warn", 192 | "jsx-a11y/aria-proptypes": "warn", 193 | "jsx-a11y/aria-role": "warn", 194 | "jsx-a11y/aria-unsupported-elements": "warn", 195 | "jsx-a11y/heading-has-content": "warn", 196 | "jsx-a11y/iframe-has-title": "warn", 197 | "jsx-a11y/img-redundant-alt": "warn", 198 | "jsx-a11y/no-access-key": "warn", 199 | "jsx-a11y/no-distracting-elements": "warn", 200 | "jsx-a11y/no-redundant-roles": "warn", 201 | "jsx-a11y/role-has-required-aria-props": "warn", 202 | "jsx-a11y/role-supports-aria-props": "warn", 203 | "jsx-a11y/scope": "warn", 204 | "react-hooks/rules-of-hooks": "error", 205 | "default-case": "off", 206 | "no-dupe-class-members": "off", 207 | "no-undef": "off", 208 | "@typescript-eslint/consistent-type-assertions": "warn", 209 | "no-array-constructor": "off", 210 | "@typescript-eslint/no-array-constructor": "warn", 211 | "@typescript-eslint/no-namespace": "error", 212 | "no-use-before-define": "off", 213 | "@typescript-eslint/no-use-before-define": [ 214 | "warn", 215 | { 216 | "functions": false, 217 | "classes": false, 218 | "variables": false, 219 | "typedefs": false 220 | } 221 | ], 222 | "no-unused-vars": "off", 223 | "@typescript-eslint/no-unused-vars": [ 224 | "warn", 225 | { "args": "none", "ignoreRestSiblings": true } 226 | ], 227 | "no-useless-constructor": "off", 228 | "@typescript-eslint/no-useless-constructor": "warn", 229 | "@typescript-eslint/no-unused-expressions": [ 230 | "error", 231 | { 232 | "allowShortCircuit": true, 233 | "allowTernary": true, 234 | "allowTaggedTemplates": true 235 | } 236 | ] 237 | }, 238 | "env": { 239 | "browser": true, 240 | "commonjs": true, 241 | "es6": true, 242 | "jest": true, 243 | "node": true 244 | }, 245 | "settings": { "react": { "version": "detect" } }, 246 | "plugins": ["import", "jsx-a11y", "react", "react-hooks"], 247 | "extends": ["../../.eslintrc"], 248 | "ignorePatterns": ["!**/*"] 249 | } 250 | -------------------------------------------------------------------------------- /externals/todos/workspace.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 1, 3 | "projects": { 4 | "todos": { 5 | "root": "apps/todos", 6 | "sourceRoot": "apps/todos/src", 7 | "projectType": "application", 8 | "schematics": {}, 9 | "architect": { 10 | "build": { 11 | "builder": "@nrwl/web:build", 12 | "options": { 13 | "outputPath": "dist/apps/todos", 14 | "index": "apps/todos/src/index.html", 15 | "main": "apps/todos/src/main.tsx", 16 | "polyfills": "apps/todos/src/polyfills.ts", 17 | "tsConfig": "apps/todos/tsconfig.app.json", 18 | "assets": [ 19 | "apps/todos/src/favicon.ico", 20 | "apps/todos/src/assets" 21 | ], 22 | "styles": [ 23 | "apps/todos/src/styles.css" 24 | ], 25 | "scripts": [], 26 | "webpackConfig": "@nrwl/react/plugins/webpack" 27 | }, 28 | "configurations": { 29 | "production": { 30 | "fileReplacements": [ 31 | { 32 | "replace": "apps/todos/src/environments/environment.ts", 33 | "with": "apps/todos/src/environments/environment.prod.ts" 34 | } 35 | ], 36 | "optimization": true, 37 | "outputHashing": "all", 38 | "sourceMap": false, 39 | "extractCss": true, 40 | "namedChunks": false, 41 | "extractLicenses": true, 42 | "vendorChunk": false, 43 | "budgets": [ 44 | { 45 | "type": "initial", 46 | "maximumWarning": "2mb", 47 | "maximumError": "5mb" 48 | } 49 | ] 50 | } 51 | } 52 | }, 53 | "serve": { 54 | "builder": "@nrwl/web:dev-server", 55 | "options": { 56 | "buildTarget": "todos:build", 57 | "proxyConfig": "apps/todos/proxy.conf.json" 58 | }, 59 | "configurations": { 60 | "production": { 61 | "buildTarget": "todos:build:production" 62 | } 63 | } 64 | }, 65 | "lint": { 66 | "builder": "@nrwl/linter:lint", 67 | "options": { 68 | "linter": "eslint", 69 | "tsConfig": [ 70 | "apps/todos/tsconfig.app.json", 71 | "apps/todos/tsconfig.spec.json" 72 | ], 73 | "exclude": [ 74 | "**/node_modules/**", 75 | "!apps/todos/**/*" 76 | ] 77 | } 78 | }, 79 | "test": { 80 | "builder": "@nrwl/jest:jest", 81 | "options": { 82 | "jestConfig": "apps/todos/jest.config.js", 83 | "passWithNoTests": true 84 | } 85 | }, 86 | "release": { 87 | "builder": "@nrwl/workspace:run-commands", 88 | "options": { 89 | "commands": [ 90 | { 91 | "command": "echo released!" 92 | } 93 | ] 94 | } 95 | } 96 | } 97 | }, 98 | "todos-e2e": { 99 | "root": "apps/todos-e2e", 100 | "sourceRoot": "apps/todos-e2e/src", 101 | "projectType": "application", 102 | "architect": { 103 | "e2e": { 104 | "builder": "@nrwl/cypress:cypress", 105 | "options": { 106 | "cypressConfig": "apps/todos-e2e/cypress.json", 107 | "tsConfig": "apps/todos-e2e/tsconfig.e2e.json", 108 | "devServerTarget": "todos:serve" 109 | }, 110 | "configurations": { 111 | "production": { 112 | "devServerTarget": "todos:serve:production" 113 | } 114 | } 115 | }, 116 | "lint": { 117 | "builder": "@nrwl/linter:lint", 118 | "options": { 119 | "linter": "eslint", 120 | "tsConfig": [ 121 | "apps/todos-e2e/tsconfig.e2e.json" 122 | ], 123 | "exclude": [ 124 | "**/node_modules/**", 125 | "!apps/todos-e2e/**/*" 126 | ] 127 | } 128 | } 129 | } 130 | }, 131 | "todos-api": { 132 | "root": "apps/todos-api", 133 | "sourceRoot": "apps/todos-api/src", 134 | "projectType": "application", 135 | "prefix": "api", 136 | "schematics": {}, 137 | "architect": { 138 | "build": { 139 | "builder": "@nrwl/node:build", 140 | "options": { 141 | "outputPath": "dist/apps/todos-api", 142 | "main": "apps/todos-api/src/main.ts", 143 | "tsConfig": "apps/todos-api/tsconfig.app.json", 144 | "assets": [ 145 | "apps/todos-api/src/assets" 146 | ] 147 | }, 148 | "configurations": { 149 | "production": { 150 | "optimization": true, 151 | "extractLicenses": true, 152 | "inspect": false, 153 | "fileReplacements": [ 154 | { 155 | "replace": "apps/todos-api/src/environments/environment.ts", 156 | "with": "apps/todos-api/src/environments/environment.prod.ts" 157 | } 158 | ] 159 | } 160 | } 161 | }, 162 | "serve": { 163 | "builder": "@nrwl/node:execute", 164 | "options": { 165 | "buildTarget": "api:build" 166 | } 167 | }, 168 | "lint": { 169 | "builder": "@nrwl/linter:lint", 170 | "options": { 171 | "linter": "eslint", 172 | "tsConfig": [ 173 | "apps/todos-api/tsconfig.app.json", 174 | "apps/todos-api/tsconfig.spec.json" 175 | ], 176 | "exclude": [ 177 | "**/node_modules/**", 178 | "!apps/todos-api/**/*" 179 | ] 180 | } 181 | }, 182 | "test": { 183 | "builder": "@nrwl/jest:jest", 184 | "options": { 185 | "jestConfig": "apps/todos-api/jest.config.js", 186 | "passWithNoTests": true 187 | } 188 | }, 189 | "release": { 190 | "builder": "@nrwl/workspace:run-commands", 191 | "options": { 192 | "commands": [ 193 | { 194 | "command": "echo released!" 195 | } 196 | ] 197 | } 198 | } 199 | } 200 | }, 201 | "api-interfaces": { 202 | "root": "libs/api-interfaces", 203 | "sourceRoot": "libs/api-interfaces/src", 204 | "projectType": "library", 205 | "schematics": {}, 206 | "architect": { 207 | "lint": { 208 | "builder": "@nrwl/linter:lint", 209 | "options": { 210 | "linter": "eslint", 211 | "tsConfig": [ 212 | "libs/api-interfaces/tsconfig.lib.json", 213 | "libs/api-interfaces/tsconfig.spec.json" 214 | ], 215 | "exclude": [ 216 | "**/node_modules/**", 217 | "!libs/api-interfaces/**/*" 218 | ] 219 | } 220 | }, 221 | "test": { 222 | "builder": "@nrwl/jest:jest", 223 | "options": { 224 | "jestConfig": "libs/api-interfaces/jest.config.js", 225 | "passWithNoTests": true 226 | } 227 | }, 228 | "release": { 229 | "builder": "@nrwl/workspace:run-commands", 230 | "options": { 231 | "commands": [ 232 | { 233 | "command": "echo released!" 234 | } 235 | ] 236 | } 237 | } 238 | } 239 | } 240 | }, 241 | "cli": { 242 | "defaultCollection": "@nrwl/react" 243 | }, 244 | "schematics": { 245 | "@nrwl/react": { 246 | "application": { 247 | "style": "css", 248 | "linter": "eslint", 249 | "babel": true 250 | }, 251 | "component": { 252 | "style": "css" 253 | }, 254 | "library": { 255 | "style": "css", 256 | "linter": "eslint" 257 | } 258 | } 259 | }, 260 | "defaultProject": "todos" 261 | } -------------------------------------------------------------------------------- /workspace.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 1, 3 | "projects": { 4 | "todos": { 5 | "root": "apps/todos", 6 | "sourceRoot": "apps/todos/src", 7 | "projectType": "application", 8 | "schematics": {}, 9 | "architect": { 10 | "build": { 11 | "builder": "@nrwl/web:build", 12 | "options": { 13 | "outputPath": "dist/apps/todos", 14 | "index": "apps/todos/src/index.html", 15 | "main": "apps/todos/src/main.tsx", 16 | "polyfills": "apps/todos/src/polyfills.ts", 17 | "tsConfig": "apps/todos/tsconfig.app.json", 18 | "assets": ["apps/todos/src/favicon.ico", "apps/todos/src/assets"], 19 | "styles": ["apps/todos/src/styles.css"], 20 | "scripts": [], 21 | "webpackConfig": "@nrwl/react/plugins/webpack" 22 | }, 23 | "configurations": { 24 | "production": { 25 | "fileReplacements": [ 26 | { 27 | "replace": "apps/todos/src/environments/environment.ts", 28 | "with": "apps/todos/src/environments/environment.prod.ts" 29 | } 30 | ], 31 | "optimization": true, 32 | "outputHashing": "all", 33 | "sourceMap": false, 34 | "extractCss": true, 35 | "namedChunks": false, 36 | "extractLicenses": true, 37 | "vendorChunk": false, 38 | "budgets": [ 39 | { 40 | "type": "initial", 41 | "maximumWarning": "2mb", 42 | "maximumError": "5mb" 43 | } 44 | ] 45 | } 46 | } 47 | }, 48 | "serve": { 49 | "builder": "@nrwl/web:dev-server", 50 | "options": { 51 | "buildTarget": "todos:build", 52 | "proxyConfig": "apps/todos/proxy.conf.json" 53 | }, 54 | "configurations": { 55 | "production": { 56 | "buildTarget": "todos:build:production" 57 | } 58 | } 59 | }, 60 | "lint": { 61 | "builder": "@nrwl/linter:lint", 62 | "options": { 63 | "linter": "eslint", 64 | "tsConfig": [ 65 | "apps/todos/tsconfig.app.json", 66 | "apps/todos/tsconfig.spec.json" 67 | ], 68 | "exclude": ["**/node_modules/**", "!apps/todos/**/*"] 69 | } 70 | }, 71 | "test": { 72 | "builder": "@nrwl/jest:jest", 73 | "options": { 74 | "jestConfig": "apps/todos/jest.config.js", 75 | "passWithNoTests": true 76 | } 77 | }, 78 | "release": { 79 | "builder": "@nrwl/workspace:run-commands", 80 | "options": { 81 | "commands": [ 82 | { 83 | "command": "echo released!" 84 | } 85 | ] 86 | } 87 | } 88 | } 89 | }, 90 | "todos-e2e": { 91 | "root": "apps/todos-e2e", 92 | "sourceRoot": "apps/todos-e2e/src", 93 | "projectType": "application", 94 | "architect": { 95 | "e2e": { 96 | "builder": "@nrwl/cypress:cypress", 97 | "options": { 98 | "cypressConfig": "apps/todos-e2e/cypress.json", 99 | "tsConfig": "apps/todos-e2e/tsconfig.e2e.json", 100 | "devServerTarget": "todos:serve" 101 | }, 102 | "configurations": { 103 | "production": { 104 | "devServerTarget": "todos:serve:production" 105 | } 106 | } 107 | }, 108 | "lint": { 109 | "builder": "@nrwl/linter:lint", 110 | "options": { 111 | "linter": "eslint", 112 | "tsConfig": ["apps/todos-e2e/tsconfig.e2e.json"], 113 | "exclude": ["**/node_modules/**", "!apps/todos-e2e/**/*"] 114 | } 115 | } 116 | } 117 | }, 118 | "todos-api": { 119 | "root": "apps/todos-api", 120 | "sourceRoot": "apps/todos-api/src", 121 | "projectType": "application", 122 | "prefix": "api", 123 | "schematics": {}, 124 | "architect": { 125 | "build": { 126 | "builder": "@nrwl/node:build", 127 | "options": { 128 | "outputPath": "dist/apps/todos-api", 129 | "main": "apps/todos-api/src/main.ts", 130 | "tsConfig": "apps/todos-api/tsconfig.app.json", 131 | "assets": ["apps/todos-api/src/assets"] 132 | }, 133 | "configurations": { 134 | "production": { 135 | "optimization": true, 136 | "extractLicenses": true, 137 | "inspect": false, 138 | "fileReplacements": [ 139 | { 140 | "replace": "apps/todos-api/src/environments/environment.ts", 141 | "with": "apps/todos-api/src/environments/environment.prod.ts" 142 | } 143 | ] 144 | } 145 | } 146 | }, 147 | "serve": { 148 | "builder": "@nrwl/node:execute", 149 | "options": { 150 | "buildTarget": "api:build" 151 | } 152 | }, 153 | "lint": { 154 | "builder": "@nrwl/linter:lint", 155 | "options": { 156 | "linter": "eslint", 157 | "tsConfig": [ 158 | "apps/todos-api/tsconfig.app.json", 159 | "apps/todos-api/tsconfig.spec.json" 160 | ], 161 | "exclude": ["**/node_modules/**", "!apps/todos-api/**/*"] 162 | } 163 | }, 164 | "test": { 165 | "builder": "@nrwl/jest:jest", 166 | "options": { 167 | "jestConfig": "apps/todos-api/jest.config.js", 168 | "passWithNoTests": true 169 | } 170 | }, 171 | "release": { 172 | "builder": "@nrwl/workspace:run-commands", 173 | "options": { 174 | "commands": [ 175 | { 176 | "command": "echo released!" 177 | } 178 | ] 179 | } 180 | } 181 | } 182 | }, 183 | "blog": { 184 | "root": "apps/blog", 185 | "sourceRoot": "apps/blog/src", 186 | "projectType": "application", 187 | "schematics": {}, 188 | "architect": { 189 | "build": { 190 | "builder": "@nrwl/web:build", 191 | "options": { 192 | "outputPath": "dist/apps/blog", 193 | "index": "apps/blog/src/index.html", 194 | "main": "apps/blog/src/main.tsx", 195 | "polyfills": "apps/blog/src/polyfills.ts", 196 | "tsConfig": "apps/blog/tsconfig.app.json", 197 | "assets": ["apps/blog/src/favicon.ico", "apps/blog/src/assets"], 198 | "styles": ["apps/blog/src/styles.css"], 199 | "scripts": [], 200 | "webpackConfig": "@nrwl/react/plugins/webpack" 201 | }, 202 | "configurations": { 203 | "production": { 204 | "fileReplacements": [ 205 | { 206 | "replace": "apps/blog/src/environments/environment.ts", 207 | "with": "apps/blog/src/environments/environment.prod.ts" 208 | } 209 | ], 210 | "optimization": true, 211 | "outputHashing": "all", 212 | "sourceMap": false, 213 | "extractCss": true, 214 | "namedChunks": false, 215 | "extractLicenses": true, 216 | "vendorChunk": false, 217 | "budgets": [ 218 | { 219 | "type": "initial", 220 | "maximumWarning": "2mb", 221 | "maximumError": "5mb" 222 | } 223 | ] 224 | } 225 | } 226 | }, 227 | "serve": { 228 | "builder": "@nrwl/web:dev-server", 229 | "options": { 230 | "buildTarget": "blog:build", 231 | "proxyConfig": "apps/blog/proxy.conf.json" 232 | }, 233 | "configurations": { 234 | "production": { 235 | "buildTarget": "blog:build:production" 236 | } 237 | } 238 | }, 239 | "lint": { 240 | "builder": "@nrwl/linter:lint", 241 | "options": { 242 | "linter": "eslint", 243 | "tsConfig": [ 244 | "apps/blog/tsconfig.app.json", 245 | "apps/blog/tsconfig.spec.json" 246 | ], 247 | "exclude": ["**/node_modules/**", "!apps/blog/**/*"] 248 | } 249 | }, 250 | "test": { 251 | "builder": "@nrwl/jest:jest", 252 | "options": { 253 | "jestConfig": "apps/blog/jest.config.js", 254 | "passWithNoTests": true 255 | } 256 | }, 257 | "release": { 258 | "builder": "@nrwl/workspace:run-commands", 259 | "options": { 260 | "commands": [ 261 | { 262 | "command": "echo released!" 263 | } 264 | ] 265 | } 266 | } 267 | } 268 | }, 269 | "blog-api": { 270 | "root": "apps/blog-api", 271 | "sourceRoot": "apps/blog-api/src", 272 | "projectType": "application", 273 | "prefix": "api", 274 | "schematics": {}, 275 | "architect": { 276 | "build": { 277 | "builder": "@nrwl/node:build", 278 | "options": { 279 | "outputPath": "dist/apps/blog-api", 280 | "main": "apps/blog-api/src/main.ts", 281 | "tsConfig": "apps/blog-api/tsconfig.app.json", 282 | "assets": ["apps/blog-api/src/assets"] 283 | }, 284 | "configurations": { 285 | "production": { 286 | "optimization": true, 287 | "extractLicenses": true, 288 | "inspect": false, 289 | "fileReplacements": [ 290 | { 291 | "replace": "apps/blog-api/src/environments/environment.ts", 292 | "with": "apps/blog-api/src/environments/environment.prod.ts" 293 | } 294 | ] 295 | } 296 | } 297 | }, 298 | "serve": { 299 | "builder": "@nrwl/node:execute", 300 | "options": { 301 | "buildTarget": "api:build" 302 | } 303 | }, 304 | "lint": { 305 | "builder": "@nrwl/linter:lint", 306 | "options": { 307 | "linter": "eslint", 308 | "tsConfig": [ 309 | "apps/blog-api/tsconfig.app.json", 310 | "apps/blog-api/tsconfig.spec.json" 311 | ], 312 | "exclude": ["**/node_modules/**", "!apps/blog-api/**/*"] 313 | } 314 | }, 315 | "test": { 316 | "builder": "@nrwl/jest:jest", 317 | "options": { 318 | "jestConfig": "apps/blog-api/jest.config.js", 319 | "passWithNoTests": true 320 | } 321 | }, 322 | "release": { 323 | "builder": "@nrwl/workspace:run-commands", 324 | "options": { 325 | "commands": [ 326 | { 327 | "command": "echo released!" 328 | } 329 | ] 330 | } 331 | } 332 | } 333 | }, 334 | "api-interfaces": { 335 | "root": "libs/api-interfaces", 336 | "sourceRoot": "libs/api-interfaces/src", 337 | "projectType": "library", 338 | "schematics": {}, 339 | "architect": { 340 | "lint": { 341 | "builder": "@nrwl/linter:lint", 342 | "options": { 343 | "linter": "eslint", 344 | "tsConfig": [ 345 | "libs/api-interfaces/tsconfig.lib.json", 346 | "libs/api-interfaces/tsconfig.spec.json" 347 | ], 348 | "exclude": ["**/node_modules/**", "!libs/api-interfaces/**/*"] 349 | } 350 | }, 351 | "test": { 352 | "builder": "@nrwl/jest:jest", 353 | "options": { 354 | "jestConfig": "libs/api-interfaces/jest.config.js", 355 | "passWithNoTests": true 356 | } 357 | }, 358 | "release": { 359 | "builder": "@nrwl/workspace:run-commands", 360 | "options": { 361 | "commands": [ 362 | { 363 | "command": "echo released!" 364 | } 365 | ] 366 | } 367 | } 368 | } 369 | } 370 | }, 371 | "cli": { 372 | "defaultCollection": "@nrwl/react" 373 | }, 374 | "schematics": { 375 | "@nrwl/react": { 376 | "application": { 377 | "style": "css", 378 | "linter": "eslint", 379 | "babel": true 380 | }, 381 | "component": { 382 | "style": "css" 383 | }, 384 | "library": { 385 | "style": "css", 386 | "linter": "eslint" 387 | } 388 | } 389 | }, 390 | "defaultProject": "todos" 391 | } 392 | --------------------------------------------------------------------------------