Last active
March 3, 2024 09:39
-
-
Save pvspain/ef74705b023dc76385aeadd3533eea81 to your computer and use it in GitHub Desktop.
build-monorepo
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#! /usr/bin/env bash | |
# This script follows the construction of a monorepo using the facilities | |
# within npm. The reference, below, is a blog article, walking through | |
# the incremental process. | |
# https://daveiscoding.com/nodejs-typescript-monorepo-via-npm-workspaces | |
# This script deviates from the blog, where we use ES2022 and | |
# ECMAScript modules, and the package source code is located in the 'src' | |
# folder from the get-go. | |
# We create a git repository, named for $MONOREPO (defined below). | |
# Each step in the process is committed, so you can examine the changes | |
# introduced by each step as git diffs. | |
# The monorepo packages are all "scoped" within @${MONOREPO}. | |
# This is not essential for a monorepo, but does provide | |
# a unique namespace for package names within the monorepo. | |
# The package is initially a Javascript NodeJS project (v16+, ECMAScript modules), | |
# then later converted to Typescript (targetting ES2022). | |
## Report and commit all changes | |
function snapshot () { | |
git add . | |
git status | |
# Combine all arguments into one string: "$*" | |
git commit -m"$*" | |
} | |
# Set name for monorepo | |
export MONOREPO=container | |
# Reset terminal | |
clear | |
# Clean up any previous execution | |
printf "\n1. Clean up any previous execution...\n\n" | |
if [ -d ${MONOREPO} ] | |
then | |
rm -rf ${MONOREPO} | |
fi | |
# Create MONOREPO and git repository | |
printf "\n2. Create monorepo directory, '${MONOREPO}', and git repository...\n\n" | |
mkdir ${MONOREPO} && | |
pushd ${MONOREPO} > /dev/null || exit | |
git init | |
# Initialise the MONOREPO npm package | |
printf "\n3. Initialise the monorepo npm package, '${MONOREPO}'...\n\n" | |
npm init -y && | |
npm pkg set main="src/index.js" type=module || exit | |
snapshot "Init monorepo package: '${MONOREPO}'." | |
# Initialise the workspaces | |
printf "\n4. Initialise the package workspaces...\n\n" | |
npm init --scope @${MONOREPO} -w packages/core -y && | |
npm init --scope @${MONOREPO} -w packages/web -y && | |
npm init --scope @${MONOREPO} -w packages/cli -y || exit | |
# Signal we are using modules in Node package | |
# Change package entry-point location to 'src/index.js' | |
npm pkg set main="src/index.js" type=module --ws || exit | |
snapshot Initialise the package workspaces. | |
# Define package dependencies | |
printf "\n5. Define package dependencies...\n\n" | |
npm install @${MONOREPO}/core -w @${MONOREPO}/web && | |
npm install @${MONOREPO}/core -w @${MONOREPO}/cli || exit | |
snapshot Define package dependencies. | |
# Add package testing files | |
printf "\n6. Add package testing files in 'src' folders...\n\n" | |
# Create 'src'folders | |
mkdir packages/core/src && | |
mkdir packages/web/src && | |
mkdir packages/cli/src || exit | |
cat << EOF > packages/core/src/index.js | |
console.log("Hello from Core!"); | |
EOF | |
cat << EOF > packages/cli/src/index.js | |
import "@${MONOREPO}/core"; | |
console.log("Hello from CLI!"); | |
EOF | |
cat << EOF > packages/web/src/index.js | |
import "@${MONOREPO}/core"; | |
console.log("Hello from Web!"); | |
EOF | |
snapshot Add package testing files. | |
# Run tests | |
printf "\n7. Run tests...\n\n" | |
node packages/cli/src/index.js && | |
node packages/web/src/index.js || exit | |
# Add "typescript" npm package | |
printf "\n8. Add 'typescript' npm package...\n\n" | |
npm install -D typescript || exit | |
# Don't track typescript package in git repo | |
printf "node_modules/typescript/\n" > .gitignore | |
snapshot Add typescript npm package. | |
# Add typescript config files | |
printf "\n9. Add typescript config files...\n\n" | |
cat << EOF > tsconfig.base.json | |
{ | |
"compilerOptions": { | |
"incremental": true, | |
"target": "es2022", | |
"module": "node16", | |
"declaration": true, | |
"sourceMap": true, | |
"strict": true, | |
"moduleResolution": "node16", | |
"esModuleInterop": true, | |
"skipLibCheck": true, | |
"forceConsistentCasingInFileNames": true, | |
"composite": true | |
} | |
} | |
EOF | |
cat << EOF > packages/core/tsconfig.json | |
{ | |
"extends": "../../tsconfig.base.json", | |
"compilerOptions": { | |
"rootDir": "src", | |
"outDir": "dist" | |
} | |
} | |
EOF | |
cat << EOF > packages/cli/tsconfig.json | |
{ | |
"extends": "../../tsconfig.base.json", | |
"references": [{ "path": "../core" }], | |
"compilerOptions": { | |
"rootDir": "src", | |
"outDir": "dist" | |
} | |
} | |
EOF | |
cp packages/cli/tsconfig.json packages/web/tsconfig.json | |
# Empty "files" array tells TypeScript to ignore all files except those in the references. | |
cat << EOF > tsconfig.json | |
{ | |
"files": [], | |
"references": [ | |
{ "path": "packages/core" }, | |
{ "path": "packages/cli" }, | |
{ "path": "packages/web" } | |
] | |
} | |
EOF | |
snapshot Add typescript config files. | |
# Convert JS files to TS | |
printf "\n10. Convert JS files to TS...\n\n" | |
mv packages/core/src/index.js packages/core/src/index.ts | |
mv packages/web/src/index.js packages/web/src/index.ts | |
mv packages/cli/src/index.js packages/cli/src/index.ts | |
snapshot Convert JS files to TS. | |
printf "\n11. Change package 'main' (index.js) location for tsc output...\n\n" | |
npm pkg set main="dist/index.js" && | |
npm pkg set main="dist/index.js" --ws || exit | |
snapshot "Change package 'main' (index.js) location for tsc output." | |
printf "\n12. Building...\n\n" | |
npx tsc --build && | |
printf "\n13. Run tests...\n\n" | |
node packages/cli/dist/index.js && | |
node packages/web/dist/index.js || exit | |
popd > /dev/null |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment