diff --git a/templates/monorepo/.gitignore b/templates/monorepo/.gitignore new file mode 100644 index 000000000..c20d8e12e --- /dev/null +++ b/templates/monorepo/.gitignore @@ -0,0 +1,12 @@ +*.log +.DS_Store +node_modules +dist + +node_modules +package-lock.json +yarn.lock +!/yarn.lock + +.yalc +yalc.lock \ No newline at end of file diff --git a/templates/monorepo/LICENSE b/templates/monorepo/LICENSE new file mode 100644 index 000000000..ac4f03896 --- /dev/null +++ b/templates/monorepo/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/templates/monorepo/README.md b/templates/monorepo/README.md new file mode 100644 index 000000000..e05e0c9e7 --- /dev/null +++ b/templates/monorepo/README.md @@ -0,0 +1,85 @@ +# TSDX Monorepo User Guide + +## Usage + +This monorepo is setup for a dummy `@mono/` NPM organization. There are 2 packages by default: + +- `@mono/react` - A placholder React component +- `@mono/utils` - A utils packages + +Unlike other TSDX templates, the developer experience for this template is currently a bit more manual. + +Your first order of business will be to search and replace `@mono` for the npm organization of your own. + +After that you can install all the dependencies in the root directory. Since the monorepo uses Lerna and Yarn Workspaces, npm CLI is not supported (only yarn). + +```sh +yarn install +``` + +This will install all dependencies in each project, build them, and symlink them via Lerna + +## Development workflow + +In one terminal, run tsdx watch in parallel: + +```sh +yarn start +``` + +This builds each package to `//dist` and runs the project in watch mode so any edits you save inside `//src` cause a rebuild to `//dist`. The results will stream to to the terminal. + +### Using the example/playground + +You can play with local packages in the Parcel-powered example/playground. + +```sh +cd example +yarn install # or yarn install +yarn start +``` + +This will start the example/playground on `localhost:1234`. If you have lerna running watch in parallel mode in one terminal, and then you run parcel, your playground will hot reload when you make changes to any imported module whose source is inside of `packages/*/src/*`. Note that to accomplish this, each package's `start` command passes TDSX the `--noClean` flag. This prevents Parcel from exploding between rebuilds because of File Not Found errors. + +Important Safety Tip: When adding/altering packages in the playground, use `alias` object in package.json. This will tell Parcel to resolve them to the filesystem instead of trying to install the package from NPM. It also fixes duplicate React errors you may run into. + +#### Yalc + +[Yalc](https://github.com/whitecolor/yalc) is an alternative to `yarn/npm link` (and Parcel aliasing) that many developers find useful because it more closely mimics how NPM works. It works kind of like a local package registry via filesystem and symlinking magic. + +To do this, install yalc globally. + +Using NPM: + +```sh +npm i yalc -g +``` + +Using Yarn: + +```sh +yarn global add yalc +``` + +Then in each package's `start` command add a [`yalc publish`](https://github.com/whitecolor/yalc#publish) or `yalc push` as an TSDX `--onSuccess` hook. + +```diff +"scripts": { +- "start": "tsdx watch --verbose --noClean", ++ "start": "tsdx watch --verbose --noClean --onSuccess yalc publish", + "build": "tsdx build --tsconfig tsconfig.build.json", + "test": "tsdx test", + "lint": "tsdx lint", + "prepublish": "npm run build" + }, +``` + +In your example directory, now add each package via yalc + +```sh +yalc add +# or +yalc link +``` + +There's definitely room for improvement with this workflow, so please contribute if you come up with something better. diff --git a/templates/monorepo/example/.gitignore b/templates/monorepo/example/.gitignore new file mode 100644 index 000000000..587e4ec7a --- /dev/null +++ b/templates/monorepo/example/.gitignore @@ -0,0 +1,3 @@ +node_modules +.cache +dist \ No newline at end of file diff --git a/templates/monorepo/example/index.html b/templates/monorepo/example/index.html new file mode 100644 index 000000000..547e2e042 --- /dev/null +++ b/templates/monorepo/example/index.html @@ -0,0 +1,14 @@ + + + + + + + Playground + + + +
+ + + diff --git a/templates/monorepo/example/index.tsx b/templates/monorepo/example/index.tsx new file mode 100644 index 000000000..af29347a9 --- /dev/null +++ b/templates/monorepo/example/index.tsx @@ -0,0 +1,14 @@ +import 'react-app-polyfill/ie11'; +import * as React from 'react'; +import * as ReactDOM from 'react-dom'; +import { Thing } from '@mono/react'; + +const App = () => { + return ( +
+ +
+ ); +}; + +ReactDOM.render(, document.getElementById('root')); diff --git a/templates/monorepo/example/package.json b/templates/monorepo/example/package.json new file mode 100644 index 000000000..55062b90a --- /dev/null +++ b/templates/monorepo/example/package.json @@ -0,0 +1,25 @@ +{ + "name": "@mono/example", + "version": "1.0.0", + "main": "index.js", + "license": "MIT", + "scripts": { + "start": "parcel index.html", + "build": "parcel build index.html" + }, + "dependencies": { + "react-app-polyfill": "^1.0.0" + }, + "alias": { + "@mono/react": "../packages/react", + "react": "../node_modules/react", + "react-dom": "../node_modules/react-dom/profiling", + "scheduler/tracing": "../node_modules/scheduler/tracing-profiling" + }, + "devDependencies": { + "@types/react": "^16.9.11", + "@types/react-dom": "^16.8.4", + "parcel": "^1.12.3", + "typescript": "^3.4.5" + } +} diff --git a/templates/monorepo/example/tsconfig.json b/templates/monorepo/example/tsconfig.json new file mode 100644 index 000000000..1e2e4fd9c --- /dev/null +++ b/templates/monorepo/example/tsconfig.json @@ -0,0 +1,18 @@ +{ + "compilerOptions": { + "allowSyntheticDefaultImports": false, + "target": "es5", + "module": "commonjs", + "jsx": "react", + "moduleResolution": "node", + "noImplicitAny": false, + "noUnusedLocals": false, + "noUnusedParameters": false, + "removeComments": true, + "strictNullChecks": true, + "preserveConstEnums": true, + "sourceMap": true, + "lib": ["es2015", "es2016", "dom"], + "types": ["node"] + } +} diff --git a/templates/monorepo/lerna.json b/templates/monorepo/lerna.json new file mode 100644 index 000000000..cc8c8c46a --- /dev/null +++ b/templates/monorepo/lerna.json @@ -0,0 +1,10 @@ +{ + "version": "0.0.0", + "registry": "https://registry.npmjs.org/", + "publishConfig": { + "access": "public" + }, + "npmClient": "yarn", + "useWorkspaces": true, + "packages": ["packages/*"] +} diff --git a/templates/monorepo/package.json b/templates/monorepo/package.json new file mode 100644 index 000000000..828ec0eed --- /dev/null +++ b/templates/monorepo/package.json @@ -0,0 +1,28 @@ +{ + "name": "mono", + "private": true, + "devDependencies": { + "@types/react": "^16.9.43", + "@types/react-dom": "^16.9.8", + "lerna": "^3.15.0", + "react": "^16.13.1", + "react-dom": "^16.13.1", + "tsdx": "^0.13.2", + "typescript": "^3.9.7" + }, + "workspaces": [ + "packages/*" + ], + "scripts": { + "lerna": "lerna", + "start": "lerna run start --stream --parallel", + "test": "lerna run test --", + "build": "lerna run build", + "prepublish": "lerna run prepublish" + }, + "prettier": { + "trailingComma": "es5", + "singleQuote": true, + "semi": true + } +} diff --git a/templates/monorepo/packages/react/README.md b/templates/monorepo/packages/react/README.md new file mode 100644 index 000000000..f8be93c50 --- /dev/null +++ b/templates/monorepo/packages/react/README.md @@ -0,0 +1,5 @@ +# @mono/react + +[![Stable release](https://img.shields.io/npm/v/@mono/utils.svg)](https://npm.im/@mono/utils) + +Official React SDK for @mono diff --git a/templates/monorepo/packages/react/package.json b/templates/monorepo/packages/react/package.json new file mode 100644 index 000000000..f8d319683 --- /dev/null +++ b/templates/monorepo/packages/react/package.json @@ -0,0 +1,36 @@ +{ + "name": "@mono/react", + "version": "0.0.0", + "description": "Official React library for @mono", + "author": "Jared Palmer", + "repository": { + "type": "git", + "url": "git+https://github.com/mono/mono.git", + "directory": "packages/react" + }, + "scripts": { + "start": "tsdx watch --tsconfig tsconfig.build.json --verbose --noClean", + "build": "tsdx build --tsconfig tsconfig.build.json", + "test": "tsdx test", + "lint": "tsdx lint", + "prepublish": "npm run build" + }, + "main": "dist/index.js", + "module": "dist/react.esm.js", + "typings": "dist/index.d.ts", + "files": [ + "README.md", + "dist" + ], + "peerDependencies": { + "react": "^16.8.0", + "react-dom": "^16.8.0" + }, + "dependencies": { + "@mono/utils": "^0.0.0", + "tslib": "^2.0.0" + }, + "publishConfig": { + "access": "public" + } +} diff --git a/templates/monorepo/packages/react/src/index.tsx b/templates/monorepo/packages/react/src/index.tsx new file mode 100644 index 000000000..717604faa --- /dev/null +++ b/templates/monorepo/packages/react/src/index.tsx @@ -0,0 +1,10 @@ +import * as React from 'react'; +import { toSlug } from '@mono/utils'; + +export interface ThingProps { + message: string; +} + +export function Thing(props: ThingProps) { + return <>{toSlug(props.message)}; +} diff --git a/templates/monorepo/packages/react/test/react.test.tsx b/templates/monorepo/packages/react/test/react.test.tsx new file mode 100644 index 000000000..962687642 --- /dev/null +++ b/templates/monorepo/packages/react/test/react.test.tsx @@ -0,0 +1,5 @@ +describe('@mono/react', () => { + it('works', () => { + expect(true).toBe(true); + }); +}); diff --git a/templates/monorepo/packages/react/tsconfig.build.json b/templates/monorepo/packages/react/tsconfig.build.json new file mode 100644 index 000000000..16bbd61d3 --- /dev/null +++ b/templates/monorepo/packages/react/tsconfig.build.json @@ -0,0 +1,4 @@ +{ + "extends": "../../tsconfig.build.json", + "include": ["src", "types", "../../types"] +} diff --git a/templates/monorepo/packages/utils/README.md b/templates/monorepo/packages/utils/README.md new file mode 100644 index 000000000..7d9e3a01d --- /dev/null +++ b/templates/monorepo/packages/utils/README.md @@ -0,0 +1,7 @@ +# @mono/utils + +[![Stable release](https://img.shields.io/npm/v/@mono/utils.svg)](https://npm.im/@mono/utils) + +Shared utilities for various `@mono` packages. + +**Important:** This package is intended for internal use by the @mono libraries. You should not use it directly in your production projects, as the APIs can and will change often without regard to sem-ver. You have been warned! diff --git a/templates/monorepo/packages/utils/package.json b/templates/monorepo/packages/utils/package.json new file mode 100644 index 000000000..28ba095e3 --- /dev/null +++ b/templates/monorepo/packages/utils/package.json @@ -0,0 +1,26 @@ +{ + "name": "@mono/utils", + "version": "0.0.0", + "description": "Internal, shared utilities", + "author": "Jared Palmer ", + "scripts": { + "start": "tsdx watch --tsconfig tsconfig.build.json --verbose --noClean", + "build": "tsdx build --tsconfig tsconfig.build.json", + "test": "tsdx test", + "lint": "tsdx lint", + "prepublish": "npm run build" + }, + "main": "dist/index.js", + "module": "dist/utils.esm.js", + "typings": "dist/index.d.ts", + "files": [ + "README.md", + "dist" + ], + "dependencies": { + "tslib": "^2.0.0" + }, + "publishConfig": { + "access": "public" + } +} diff --git a/templates/monorepo/packages/utils/src/index.ts b/templates/monorepo/packages/utils/src/index.ts new file mode 100644 index 000000000..d9aae00a9 --- /dev/null +++ b/templates/monorepo/packages/utils/src/index.ts @@ -0,0 +1,19 @@ +/** + * Return a slugified copy of a string. + * + * @param {string} str The string to be slugified + * @return {string} The slugified string. + */ +export function toSlug(str: string): string { + let s = str; + if (!s) { + return ''; + } + s = s.toLowerCase().trim(); + s = s.replace(/ & /g, ' and '); + s = s.replace(/[ ]+/g, '-'); + s = s.replace(/[-]+/g, '-'); + s = s.replace(/[^a-z0-9-]+/g, ''); + s = s.length > 32 ? s.substr(0, 32) : s; + return s; +} diff --git a/templates/monorepo/packages/utils/test/utils.test.tsx b/templates/monorepo/packages/utils/test/utils.test.tsx new file mode 100644 index 000000000..2affdb3f6 --- /dev/null +++ b/templates/monorepo/packages/utils/test/utils.test.tsx @@ -0,0 +1,5 @@ +describe('@mono/utils', () => { + it('works', () => { + expect(true).toBe(true); + }); +}); diff --git a/templates/monorepo/packages/utils/tsconfig.build.json b/templates/monorepo/packages/utils/tsconfig.build.json new file mode 100644 index 000000000..e34f92a29 --- /dev/null +++ b/templates/monorepo/packages/utils/tsconfig.build.json @@ -0,0 +1,4 @@ +{ + "extends": "../../tsconfig.build.json", + "include": ["src", "types", "../../types"] +} diff --git a/templates/monorepo/tsconfig.build.json b/templates/monorepo/tsconfig.build.json new file mode 100644 index 000000000..10182cfe8 --- /dev/null +++ b/templates/monorepo/tsconfig.build.json @@ -0,0 +1,17 @@ +{ + "compilerOptions": { + "module": "esnext", + "lib": ["dom", "esnext"], + "importHelpers": true, + "declaration": true, + "sourceMap": true, + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true, + "moduleResolution": "node", + "jsx": "react", + "esModuleInterop": true + } +} diff --git a/templates/monorepo/tsconfig.json b/templates/monorepo/tsconfig.json new file mode 100644 index 000000000..58dd30de7 --- /dev/null +++ b/templates/monorepo/tsconfig.json @@ -0,0 +1,14 @@ +{ + "extends": "./tsconfig.build.json", + "include": ["packages", "types", "scripts", "example"], + "compilerOptions": { + "allowJs": false, + "baseUrl": ".", + "typeRoots": ["./node_modules/@types", "./types"], + "paths": { + "@mono/utils": ["packages/eval/src"], + "@mono/react": ["packages/react/src"], + "$test/*": ["test/*"] + } + } +} diff --git a/templates/monorepo/types/global.d.ts b/templates/monorepo/types/global.d.ts new file mode 100644 index 000000000..cd09ec42b --- /dev/null +++ b/templates/monorepo/types/global.d.ts @@ -0,0 +1,6 @@ +// Declare global variables for TypeScript and VSCode. +// Do not rename this file or move these types into index.d.ts +// @see https://code.visualstudio.com/docs/nodejs/working-with-javascript#_global-variables-and-type-checking +declare const __DEV__: boolean; +declare const __VERSION__: string; +declare const $FixMe: any;