chore(): start moving some packages to the core directory (#7215)
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
const signalExit = require(`signal-exit`);
|
||||
|
||||
const cleanupTasks = new Set();
|
||||
|
||||
exports.registerCleanupTask = (taskFn) => {
|
||||
cleanupTasks.add(taskFn);
|
||||
return () => {
|
||||
const result = taskFn();
|
||||
cleanupTasks.delete(taskFn);
|
||||
return result;
|
||||
};
|
||||
};
|
||||
|
||||
signalExit(() => {
|
||||
if (cleanupTasks.size) {
|
||||
console.log(`Process exitted in middle of publishing - cleaning up`);
|
||||
cleanupTasks.forEach((taskFn) => taskFn());
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,79 @@
|
||||
const startVerdaccio = require(`verdaccio`).default
|
||||
|
||||
const fs = require(`fs-extra`)
|
||||
const _ = require(`lodash`)
|
||||
|
||||
let VerdaccioInitPromise = null
|
||||
|
||||
const { verdaccioConfig } = require(`./verdaccio-config`)
|
||||
const { publishPackage } = require(`./publish-package`)
|
||||
const { installPackages } = require(`./install-packages`)
|
||||
|
||||
const startServer = () => {
|
||||
if (VerdaccioInitPromise) {
|
||||
return VerdaccioInitPromise
|
||||
}
|
||||
|
||||
console.log(`Starting local verdaccio server`)
|
||||
|
||||
// clear storage
|
||||
fs.removeSync(verdaccioConfig.storage)
|
||||
|
||||
VerdaccioInitPromise = new Promise((resolve) => {
|
||||
startVerdaccio(
|
||||
verdaccioConfig,
|
||||
verdaccioConfig.port,
|
||||
verdaccioConfig.storage,
|
||||
`1.0.0`,
|
||||
`medusa-dev`,
|
||||
(webServer, addr, pkgName, pkgVersion) => {
|
||||
// console.log(webServer)
|
||||
webServer.listen(addr.port || addr.path, addr.host, () => {
|
||||
console.log(`Started local verdaccio server`)
|
||||
|
||||
resolve()
|
||||
})
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
return VerdaccioInitPromise
|
||||
}
|
||||
|
||||
exports.startVerdaccio = startServer
|
||||
|
||||
exports.publishPackagesLocallyAndInstall = async ({
|
||||
packagesToPublish,
|
||||
localPackages,
|
||||
packageNameToPath,
|
||||
ignorePackageJSONChanges,
|
||||
yarnWorkspaceRoot,
|
||||
externalRegistry,
|
||||
root,
|
||||
}) => {
|
||||
await startServer()
|
||||
|
||||
const versionPostFix = Date.now()
|
||||
|
||||
const newlyPublishedPackageVersions = {}
|
||||
|
||||
for (const packageName of packagesToPublish) {
|
||||
newlyPublishedPackageVersions[packageName] = await publishPackage({
|
||||
packageName,
|
||||
packagesToPublish,
|
||||
packageNameToPath,
|
||||
versionPostFix,
|
||||
ignorePackageJSONChanges,
|
||||
root,
|
||||
})
|
||||
}
|
||||
|
||||
const packagesToInstall = _.intersection(packagesToPublish, localPackages)
|
||||
|
||||
await installPackages({
|
||||
packagesToInstall,
|
||||
yarnWorkspaceRoot,
|
||||
newlyPublishedPackageVersions,
|
||||
externalRegistry,
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,163 @@
|
||||
const path = require(`path`)
|
||||
const fs = require(`fs-extra`)
|
||||
|
||||
const { promisifiedSpawn } = require(`../utils/promisified-spawn`)
|
||||
const { registryUrl } = require(`./verdaccio-config`)
|
||||
|
||||
const installPackages = async ({
|
||||
packagesToInstall,
|
||||
yarnWorkspaceRoot,
|
||||
newlyPublishedPackageVersions,
|
||||
externalRegistry,
|
||||
}) => {
|
||||
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: yarnVersion } = await promisifiedSpawn([
|
||||
`yarn`,
|
||||
[`--version`],
|
||||
{ stdio: `pipe` },
|
||||
])
|
||||
const workspaceCommand = !yarnVersion.startsWith("1") ? "list" : "info"
|
||||
|
||||
const { stdout } = await promisifiedSpawn([
|
||||
`yarn`,
|
||||
[`workspaces`, workspaceCommand, `--json`],
|
||||
{ stdio: `pipe` },
|
||||
])
|
||||
|
||||
let workspacesLayout
|
||||
try {
|
||||
workspacesLayout = JSON.parse(JSON.parse(stdout).data)
|
||||
} catch (e) {
|
||||
/*
|
||||
Yarn 1.22 doesn't output pure json - it has leading and trailing text:
|
||||
```
|
||||
$ yarn workspaces info --json
|
||||
yarn workspaces v1.22.0
|
||||
{
|
||||
"z": {
|
||||
"location": "z",
|
||||
"workspaceDependencies": [],
|
||||
"mismatchedWorkspaceDependencies": []
|
||||
},
|
||||
"y": {
|
||||
"location": "y",
|
||||
"workspaceDependencies": [],
|
||||
"mismatchedWorkspaceDependencies": []
|
||||
}
|
||||
}
|
||||
Done in 0.48s.
|
||||
```
|
||||
So we need to do some sanitization. We find JSON by matching substring
|
||||
that starts with `{` and ends with `}`
|
||||
*/
|
||||
|
||||
const regex = /^[^{]*({.*})[^}]*$/gs
|
||||
const sanitizedStdOut = regex.exec(stdout)
|
||||
if (sanitizedStdOut?.length >= 2) {
|
||||
// pick content of first (and only) capturing group
|
||||
const jsonString = sanitizedStdOut[1]
|
||||
try {
|
||||
workspacesLayout = JSON.parse(jsonString)
|
||||
} catch (e) {
|
||||
console.error(
|
||||
`Failed to parse "sanitized" output of "yarn workspaces info" command.\n\nSanitized string: "${jsonString}`
|
||||
)
|
||||
// not exitting here, because we have general check for `workspacesLayout` being set below
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!workspacesLayout) {
|
||||
console.error(
|
||||
`Couldn't parse output of "yarn workspaces info" command`,
|
||||
stdout
|
||||
)
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
const handleDeps = (deps) => {
|
||||
if (!deps) {
|
||||
return false
|
||||
}
|
||||
|
||||
let changed = false
|
||||
Object.keys(deps).forEach((depName) => {
|
||||
if (packagesToInstall.includes(depName)) {
|
||||
deps[depName] = `medusa-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 @medusa-dev`)
|
||||
fs.outputJSONSync(pkgJsonPath, pkg, {
|
||||
spaces: 2,
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
// package.json files are changed - so we just want to install
|
||||
// using verdaccio registry
|
||||
const yarnCommands = [`install`]
|
||||
|
||||
if (!externalRegistry) {
|
||||
yarnCommands.push(`--registry=${registryUrl}`)
|
||||
}
|
||||
|
||||
installCmd = [`yarn`, yarnCommands]
|
||||
} else {
|
||||
const yarnCommands = [
|
||||
`add`,
|
||||
...packagesToInstall.map((packageName) => {
|
||||
const packageVersion = newlyPublishedPackageVersions[packageName]
|
||||
return `${packageName}@${packageVersion}`
|
||||
}),
|
||||
`--exact`,
|
||||
]
|
||||
|
||||
if (!externalRegistry) {
|
||||
yarnCommands.push(`--registry=${registryUrl}`)
|
||||
}
|
||||
|
||||
installCmd = [`yarn`, yarnCommands]
|
||||
}
|
||||
|
||||
try {
|
||||
await promisifiedSpawn(installCmd)
|
||||
|
||||
console.log(`Installation complete`)
|
||||
} catch (error) {
|
||||
console.error(`Installation failed`, error)
|
||||
process.exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
exports.installPackages = installPackages
|
||||
@@ -0,0 +1,158 @@
|
||||
const fs = require(`fs-extra`)
|
||||
const path = require(`path`)
|
||||
|
||||
const { promisifiedSpawn } = require(`../utils/promisified-spawn`)
|
||||
const { registryUrl } = require(`./verdaccio-config`)
|
||||
|
||||
const NPMRCContent = `${registryUrl.replace(
|
||||
/https?:/g,
|
||||
``
|
||||
)}/:_authToken="medusa-dev"`
|
||||
|
||||
const {
|
||||
getMonorepoPackageJsonPath,
|
||||
} = require(`../utils/get-monorepo-package-json-path`)
|
||||
const { registerCleanupTask } = require(`./cleanup-tasks`)
|
||||
|
||||
/**
|
||||
* Edit package.json to:
|
||||
* - adjust version to temporary one
|
||||
* - change version selectors for dependencies that
|
||||
* will be published, to make sure that yarn
|
||||
* install them in local site
|
||||
*/
|
||||
const adjustPackageJson = ({
|
||||
monoRepoPackageJsonPath,
|
||||
packageName,
|
||||
versionPostFix,
|
||||
packagesToPublish,
|
||||
ignorePackageJSONChanges,
|
||||
packageNameToPath,
|
||||
}) => {
|
||||
// we need to check if package depend on any other package to will be published and
|
||||
// adjust version selector to point to dev version of package so local registry is used
|
||||
// for dependencies.
|
||||
|
||||
const monorepoPKGjsonString = fs.readFileSync(
|
||||
monoRepoPackageJsonPath,
|
||||
`utf-8`
|
||||
)
|
||||
const monorepoPKGjson = JSON.parse(monorepoPKGjsonString)
|
||||
|
||||
monorepoPKGjson.version = `${monorepoPKGjson.version}-dev-${versionPostFix}`
|
||||
packagesToPublish.forEach((packageThatWillBePublished) => {
|
||||
if (
|
||||
monorepoPKGjson.dependencies &&
|
||||
monorepoPKGjson.dependencies[packageThatWillBePublished]
|
||||
) {
|
||||
const currentVersion = JSON.parse(
|
||||
fs.readFileSync(
|
||||
getMonorepoPackageJsonPath({
|
||||
packageName: packageThatWillBePublished,
|
||||
packageNameToPath,
|
||||
}),
|
||||
`utf-8`
|
||||
)
|
||||
).version
|
||||
|
||||
monorepoPKGjson.dependencies[
|
||||
packageThatWillBePublished
|
||||
] = `${currentVersion}-dev-${versionPostFix}`
|
||||
}
|
||||
})
|
||||
|
||||
const temporaryMonorepoPKGjsonString = JSON.stringify(monorepoPKGjson)
|
||||
|
||||
const unignorePackageJSONChanges = ignorePackageJSONChanges(packageName, [
|
||||
monorepoPKGjsonString,
|
||||
temporaryMonorepoPKGjsonString,
|
||||
])
|
||||
|
||||
// change version and dependency versions
|
||||
fs.outputFileSync(monoRepoPackageJsonPath, temporaryMonorepoPKGjsonString)
|
||||
|
||||
return {
|
||||
newPackageVersion: monorepoPKGjson.version,
|
||||
unadjustPackageJson: registerCleanupTask(() => {
|
||||
// restore original package.json
|
||||
fs.outputFileSync(monoRepoPackageJsonPath, monorepoPKGjsonString)
|
||||
unignorePackageJSONChanges()
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Anonymous publishing require dummy .npmrc
|
||||
* See https://github.com/verdaccio/verdaccio/issues/212#issuecomment-308578500
|
||||
* This is `npm publish` (as in linked comment) and `yarn publish` requirement.
|
||||
* This is not verdaccio restriction.
|
||||
*/
|
||||
const createTemporaryNPMRC = ({ pathToPackage, root }) => {
|
||||
const NPMRCPathInPackage = path.join(pathToPackage, `.npmrc`)
|
||||
fs.outputFileSync(NPMRCPathInPackage, NPMRCContent)
|
||||
|
||||
const NPMRCPathInRoot = path.join(root, `.npmrc`)
|
||||
fs.outputFileSync(NPMRCPathInRoot, NPMRCContent)
|
||||
|
||||
return registerCleanupTask(() => {
|
||||
fs.removeSync(NPMRCPathInPackage)
|
||||
fs.removeSync(NPMRCPathInRoot)
|
||||
})
|
||||
}
|
||||
|
||||
const publishPackage = async ({
|
||||
packageName,
|
||||
packagesToPublish,
|
||||
versionPostFix,
|
||||
ignorePackageJSONChanges,
|
||||
packageNameToPath,
|
||||
root,
|
||||
}) => {
|
||||
const monoRepoPackageJsonPath = getMonorepoPackageJsonPath({
|
||||
packageName,
|
||||
packageNameToPath,
|
||||
})
|
||||
|
||||
const { unadjustPackageJson, newPackageVersion } = adjustPackageJson({
|
||||
monoRepoPackageJsonPath,
|
||||
packageName,
|
||||
packageNameToPath,
|
||||
versionPostFix,
|
||||
packagesToPublish,
|
||||
ignorePackageJSONChanges,
|
||||
})
|
||||
|
||||
const pathToPackage = path.dirname(monoRepoPackageJsonPath)
|
||||
|
||||
const uncreateTemporaryNPMRC = createTemporaryNPMRC({ pathToPackage, root })
|
||||
|
||||
// npm publish
|
||||
const publishCmd = [
|
||||
`npm`,
|
||||
[`publish`, `--tag`, `medusa-dev`, `--registry=${registryUrl}`],
|
||||
{
|
||||
cwd: pathToPackage,
|
||||
},
|
||||
]
|
||||
|
||||
console.log(
|
||||
`Publishing ${packageName}@${newPackageVersion} to local registry`
|
||||
)
|
||||
try {
|
||||
await promisifiedSpawn(publishCmd)
|
||||
|
||||
console.log(
|
||||
`Published ${packageName}@${newPackageVersion} to local registry`
|
||||
)
|
||||
} catch (e) {
|
||||
console.error(`Failed to publish ${packageName}@${newPackageVersion}`, e)
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
uncreateTemporaryNPMRC()
|
||||
unadjustPackageJson()
|
||||
|
||||
return newPackageVersion
|
||||
}
|
||||
|
||||
exports.publishPackage = publishPackage
|
||||
@@ -0,0 +1,33 @@
|
||||
const path = require(`path`)
|
||||
const os = require(`os`)
|
||||
|
||||
const verdaccioConfig = {
|
||||
storage: path.join(os.tmpdir(), `verdaccio`, `storage`),
|
||||
port: 4873, // default
|
||||
max_body_size: `1000mb`,
|
||||
web: {
|
||||
enable: true,
|
||||
title: `gatsby-dev`,
|
||||
},
|
||||
logs: [{ type: `stdout`, format: `pretty-timestamped`, level: `warn` }],
|
||||
packages: {
|
||||
"**": {
|
||||
access: `$all`,
|
||||
publish: `$all`,
|
||||
proxy: `npmjs`,
|
||||
},
|
||||
},
|
||||
uplinks: {
|
||||
npmjs: {
|
||||
url: `https://registry.npmjs.org/`,
|
||||
// default is 2 max_fails - on flaky networks that cause a lot of failed installations
|
||||
max_fails: 10,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
exports.verdaccioConfig = verdaccioConfig
|
||||
|
||||
const registryUrl = `http://localhost:${verdaccioConfig.port}`
|
||||
|
||||
exports.registryUrl = registryUrl
|
||||
Reference in New Issue
Block a user