Skip to content

Commit

Permalink
feat(gatsby-dev-cli): add initial support for handling yarn workspaces (
Browse files Browse the repository at this point in the history
#15649)

* don't add duplicates

* feat(gatsby-dev-cli): add initial support for handling yarn workspaces

* Update packages/gatsby-dev-cli/src/watch.js

Co-Authored-By: Sidhartha Chatterjee <me@sidharthachatterjee.com>
  • Loading branch information
2 people authored and GatsbyJS Bot committed Jul 12, 2019
1 parent 4d5bf48 commit 28aeffe
Show file tree
Hide file tree
Showing 6 changed files with 124 additions and 35 deletions.
1 change: 1 addition & 0 deletions packages/gatsby-dev-cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"configstore": "^3.1.0",
"del": "^3.0.0",
"execa": "^1.0.0",
"find-yarn-workspace-root": "^1.2.1",
"fs-extra": "^4.0.1",
"is-absolute": "^0.2.6",
"lodash": "^4.17.10",
Expand Down
6 changes: 6 additions & 0 deletions packages/gatsby-dev-cli/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ const argv = require(`yargs`)
`Set path to Gatsby repository.
You typically only need to configure this once.`
)
.nargs(`force-install`, 0)
.describe(
`force-install`,
`Disables copying files into node_modules and forces usage of local npm repository.`
)
.alias(`C`, `copy-all`)
.nargs(`C`, 0)
.describe(
Expand Down Expand Up @@ -99,5 +104,6 @@ watch(gatsbyLocation, argv.packages, {
localPackages,
quiet: argv.quiet,
scanOnce: argv.scanOnce,
forceInstall: argv.forceInstall,
monoRepoPackages,
})
3 changes: 2 additions & 1 deletion packages/gatsby-dev-cli/src/local-npm-registry/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ exports.publishPackagesLocallyAndInstall = async ({
localPackages,
root,
ignorePackageJSONChanges,
yarnWorkspaceRoot,
}) => {
await startServer()

Expand All @@ -64,5 +65,5 @@ exports.publishPackagesLocallyAndInstall = async ({

const packagesToInstall = _.intersection(packagesToPublish, localPackages)

await installPackages({ packagesToInstall })
await installPackages({ packagesToInstall, yarnWorkspaceRoot })
}
82 changes: 71 additions & 11 deletions packages/gatsby-dev-cli/src/local-npm-registry/install-packages.js
Original file line number Diff line number Diff line change
@@ -1,22 +1,82 @@
const path = require(`path`)
const fs = require(`fs-extra`)

const { promisifiedSpawn } = require(`../utils/promisified-spawn`)
const { registryUrl } = require(`./verdaccio-config`)

const installPackages = async ({ packagesToInstall }) => {
const installCmd = [
`yarn`,
[
`add`,
...packagesToInstall.map(packageName => `${packageName}@gatsby-dev`),
`--registry=${registryUrl}`,
`--exact`,
],
]

const installPackages = async ({ packagesToInstall, yarnWorkspaceRoot }) => {
console.log(
`Installing packages from local registry:\n${packagesToInstall
.map(packageAndVersion => ` - ${packageAndVersion}`)
.join(`\n`)}`
)
let installCmd
if (yarnWorkspaceRoot) {
// this is very hacky - given root, we run `yarn workspaces info`
// to get list of all workspaces and their locations, and manually
// edit package.json file for packages we want to install
// to make sure there are no mismatched versions of same package
// in workspaces which should preserve node_modules structure
// (packages being mostly hoisted to top-level node_modules)

const { stdout } = await promisifiedSpawn([
`yarn`,
[`workspaces`, `info`, `--json`],
{ stdio: `pipe` },
])

const workspacesLayout = JSON.parse(JSON.parse(stdout).data)

const handleDeps = deps => {
if (!deps) {
return false
}

let changed = false
Object.keys(deps).forEach(depName => {
if (packagesToInstall.includes(depName)) {
deps[depName] = `gatsby-dev`
changed = true
}
})
return changed
}

Object.keys(workspacesLayout).forEach(workspaceName => {
const { location } = workspacesLayout[workspaceName]
const pkgJsonPath = path.join(yarnWorkspaceRoot, location, `package.json`)
if (!fs.existsSync(pkgJsonPath)) {
return
}
const pkg = JSON.parse(fs.readFileSync(pkgJsonPath, `utf8`))

let changed = false
changed |= handleDeps(pkg.dependencies)
changed |= handleDeps(pkg.devDependencies)
changed |= handleDeps(pkg.peerDependencies)

if (changed) {
console.log(`Changing deps in ${pkgJsonPath} to use @gatsby-dev`)
fs.outputJSONSync(pkgJsonPath, pkg, {
spaces: 2,
})
}
})

// package.json files are changed - so we just want to install
// using verdaccio registry
installCmd = [`yarn`, [`install`, `--registry=${registryUrl}`]]
} else {
installCmd = [
`yarn`,
[
`add`,
...packagesToInstall.map(packageName => `${packageName}@gatsby-dev`),
`--registry=${registryUrl}`,
`--exact`,
],
]
}

try {
await promisifiedSpawn(installCmd)
Expand Down
57 changes: 35 additions & 22 deletions packages/gatsby-dev-cli/src/watch.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ const _ = require(`lodash`)
const del = require(`del`)
const fs = require(`fs-extra`)
const path = require(`path`)
const findWorkspaceRoot = require(`find-yarn-workspace-root`)

const { publishPackagesLocallyAndInstall } = require(`./local-npm-registry`)
const { checkDepsChanges } = require(`./utils/check-deps-changes`)
Expand All @@ -23,11 +24,20 @@ const MAX_COPY_RETRIES = 3
* non-existant packages break on('ready')
* See: https://github.com/paulmillr/chokidar/issues/449
*/
function watch(
async function watch(
root,
packages,
{ scanOnce, quiet, monoRepoPackages, localPackages }
{ scanOnce, quiet, forceInstall, monoRepoPackages, localPackages }
) {
// const packagesToInstall = [`gatsby`]
// determine if in yarn workspace - if in workspace, force using verdaccio
// as current logic of copying files will not work correctly.
const yarnWorkspaceRoot = findWorkspaceRoot()
if (yarnWorkspaceRoot) {
console.log(`Yarn workspace found.`)
forceInstall = true
}

let afterPackageInstallation = false
let queuedCopies = []

Expand Down Expand Up @@ -103,19 +113,30 @@ function watch(
? _.intersection(packages, seenPackages)
: seenPackages

let packagesToInstall = []
let ignoredPackageJSON = new Map()
const ignorePackageJSONChanges = (packageName, contentArray) => {
ignoredPackageJSON.set(packageName, contentArray)

const getPackagesToInstall = packages =>
packages.forEach(pkg => {
if (localPackages.includes(pkg)) {
packagesToInstall.push(pkg)
}
if (depTree[pkg]) {
getPackagesToInstall([...depTree[pkg]])
}
})
return () => {
ignoredPackageJSON.delete(packageName)
}
}

if (forceInstall) {
try {
await publishPackagesLocallyAndInstall({
packagesToPublish: allPackagesToWatch,
root,
localPackages,
ignorePackageJSONChanges,
yarnWorkspaceRoot,
})
} catch (e) {
console.log(e)
}

getPackagesToInstall(allPackagesToWatch)
process.exit()
}

if (allPackagesToWatch.length === 0) {
console.error(`There are no packages to watch.`)
Expand All @@ -140,18 +161,10 @@ function watch(
let allCopies = []
const packagesToPublish = new Set()
let isInitialScan = true
let ignoredPackageJSON = new Map()

const waitFor = new Set()
let anyPackageNotInstalled = false

const ignorePackageJSONChanges = (packageName, contentArray) => {
ignoredPackageJSON.set(packageName, contentArray)

return () => {
ignoredPackageJSON.delete(ignoredPackageJSON)
}
}

const watchEvents = [`change`, `add`]

chokidar
Expand Down
10 changes: 9 additions & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -9256,6 +9256,14 @@ find-versions@^3.0.0:
array-uniq "^2.0.0"
semver-regex "^2.0.0"

find-yarn-workspace-root@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/find-yarn-workspace-root/-/find-yarn-workspace-root-1.2.1.tgz#40eb8e6e7c2502ddfaa2577c176f221422f860db"
integrity sha512-dVtfb0WuQG+8Ag2uWkbG79hOUzEsRrhBzgfn86g2sJPkzmcpGdghbNTfUKGTxymFrY/tLIodDzLoW9nOJ4FY8Q==
dependencies:
fs-extra "^4.0.3"
micromatch "^3.1.4"

findup-sync@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-2.0.0.tgz#9326b1488c22d1a6088650a86901b2d9a90a2cbc"
Expand Down Expand Up @@ -9483,7 +9491,7 @@ fs-extra@^1.0.0:
jsonfile "^2.1.0"
klaw "^1.0.0"

fs-extra@^4.0.1, fs-extra@^4.0.2:
fs-extra@^4.0.1, fs-extra@^4.0.2, fs-extra@^4.0.3:
version "4.0.3"
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-4.0.3.tgz#0d852122e5bc5beb453fb028e9c0c9bf36340c94"
dependencies:
Expand Down

0 comments on commit 28aeffe

Please sign in to comment.