Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update: Use npm for install, update and uninstall where required (fixes #175) #189

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
23 changes: 18 additions & 5 deletions lib/integration/Plugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ export default class Plugin {
* @returns {boolean|null}
*/
get isUpToDate () {
if (!this.hasFrameworkCompatibleVersion) return true;
if (!this.hasFrameworkCompatibleVersion) return true
const canCheckSourceAgainstProject = (this.latestSourceVersion && this.projectVersion)
if (!canCheckSourceAgainstProject) return null
const isLatestVersion = (this.projectVersion === this.latestSourceVersion)
Expand Down Expand Up @@ -187,8 +187,9 @@ export default class Plugin {
if (!this.isLocalSource) throw new Error('Plugin name or version must be a path to the source')
if (this.isLocalSourceZip) throw new Error('Cannot install from zip files')
this._sourceInfo = await new Promise((resolve, reject) => {
// get bower.json data
// get package.json or bower.json data
const paths = [
path.resolve(this.cwd, `${this.sourcePath}/package.json`),
path.resolve(this.cwd, `${this.sourcePath}/bower.json`)
]
const bowerJSON = paths.reduce((bowerJSON, bowerJSONPath) => {
Expand All @@ -211,6 +212,7 @@ export default class Plugin {
const perform = async (attemptCount = 0) => {
try {
return await new Promise((resolve, reject) => {
// TODO: npm implementation
bower.commands.info(`${this.packageName}`, null, { cwd: this.cwd, registry: this.BOWER_REGISTRY_CONFIG })
.on('end', resolve)
.on('error', reject)
Expand All @@ -227,12 +229,19 @@ export default class Plugin {
this._versionsInfo = info.versions.filter(version => semverOptions.includePrerelease ? true : !semver.prerelease(version))
}

async refetchProjectInfo () {
this._projectInfo = null
return this.fetchProjectInfo()
}

async fetchProjectInfo () {
if (this._projectInfo) return this._projectInfo
this._projectInfo = null
this._projectInfo = await new Promise((resolve, reject) => {
// get bower.json data
// get package.json or bower.json data
globs([
`${this.cwd.replace(/\\/g, '/')}/src/node_modules/${this.packageName}/.package.json`,
`${this.cwd.replace(/\\/g, '/')}/src/node_modules/${this.packageName}/package.json`,
`${this.cwd.replace(/\\/g, '/')}/src/*/${this.packageName}/.bower.json`,
`${this.cwd.replace(/\\/g, '/')}/src/*/${this.packageName}/bower.json`
], (err, matches) => {
Expand All @@ -242,8 +251,10 @@ export default class Plugin {
if (!match) {
// widen the search
globs([
`${this.cwd.replace(/\\/g, '/')}/src/**/.bower.json`,
`${this.cwd.replace(/\\/g, '/')}/src/**/bower.json`
`${this.cwd.replace(/\\/g, '/')}/src/node_modules/adapt-*/.package.json`,
`${this.cwd.replace(/\\/g, '/')}/src/node_modules/adapt-*/package.json`,
`${this.cwd.replace(/\\/g, '/')}/src/*/adapt-*/.bower.json`,
`${this.cwd.replace(/\\/g, '/')}/src/*/adapt-*/bower.json`
], (err, matches) => {
if (err) return resolve(null)
const tester = new RegExp(`/${this.packageName}/`, 'i')
Expand All @@ -268,6 +279,7 @@ export default class Plugin {
const perform = async (attemptCount = 0) => {
try {
return await new Promise((resolve, reject) => {
// TODO: npm implementation
bower.commands.info(`${this.packageName}@${version}`, null, { cwd: this.cwd, registry: this.BOWER_REGISTRY_CONFIG })
.on('end', resolve)
.on('error', reject)
Expand Down Expand Up @@ -353,6 +365,7 @@ export default class Plugin {
if (this._repositoryUrl) return this._repositoryUrl
if (this.isLocalSource) return
const url = await new Promise((resolve, reject) => {
// TODO: npm implementation
bower.commands.lookup(this.packageName, { cwd: this.cwd, registry: this.BOWER_REGISTRY_CONFIG })
.on('end', resolve)
.on('error', reject)
Expand Down
21 changes: 19 additions & 2 deletions lib/integration/PluginManagement/install.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import Target from '../Target.js'
import bower from 'bower'
import { difference } from 'lodash-es'
import path from 'path'
import { install as npmInstall } from './npm.js'

export default async function install ({
plugins,
Expand All @@ -20,7 +21,10 @@ export default async function install ({
logger = null
}) {
cwd = path.resolve(process.cwd(), cwd)
isClean && await new Promise(resolve => bower.commands.cache.clean().on('end', resolve))
isClean && await new Promise(resolve => {
// TODO: npm implementation
bower.commands.cache.clean().on('end', resolve)
})
const project = new Project({ cwd, logger })
project.tryThrowInvalidPath()

Expand All @@ -40,8 +44,21 @@ export default async function install ({
await eachOfSeriesProgress(
installTargetsToBeInstalled,
target => target.install({ clone: dev }),
percentage => logger?.logProgress?.(`${chalk.bold.cyan('<info>')} Installing plugins ${percentage}% complete`)
percentage => logger?.logProgress?.(`${chalk.bold.cyan('<info>')} Installing plugins ${(percentage / (project.isNPM ? 2 : 1))}% complete`)
)
if (project.isNPM) {
// Batch install npm plugins as it's faster
const installArgs = installTargetsToBeInstalled
.filter(target => target.isNPMInstall)
.map(target => `${target.packageName}@${target.versionToApply}`)
const outputPath = path.join(cwd, 'src')
await npmInstall({ logger, cwd: outputPath, args: installArgs })
await eachOfSeriesProgress(
installTargetsToBeInstalled,
target => target.postInstall(),
percentage => logger?.logProgress?.(`${chalk.bold.cyan('<info>')} Installing plugins ${50 + (percentage / 2)}% complete`)
)
}
logger?.log(`${chalk.bold.cyan('<info>')} Installing plugins 100% complete`)
const manifestDependencies = await project.getManifestDependencies()
await updateManifest({ logger, project, targets, manifestDependencies, isInteractive })
Expand Down
43 changes: 43 additions & 0 deletions lib/integration/PluginManagement/npm.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { exec } from 'child_process'
import path from 'path'

export async function execute ({
logger,
command,
cwd,
args = []
} = {}) {
cwd = path.resolve(process.cwd(), cwd)
await new Promise((resolve, reject) => {
exec([(process.platform === 'win32' ? 'npm.cmd' : 'npm'), '--unsafe-perm', command, ...args].join(' '), {
cwd
}, (err, stdout, stderr) => {
if (!err) return resolve()
reject(stderr)
})
})
}

export async function install ({
logger,
cwd,
args = []
} = {}) {
await execute({ logger, command: 'install', cwd, args })
}

export async function update ({
logger,
cwd,
args = []
} = {}) {
await execute({ logger, command: 'update', cwd, args })
}

export async function uninstall ({
logger,
cwd,
args = []
} = {}) {
await execute({ logger, command: 'uninstall', cwd, args })
}
3 changes: 3 additions & 0 deletions lib/integration/PluginManagement/register.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export default async function register ({
const BOWER_REGISTRY_CONFIG = getBowerRegistryConfig({ cwd })
logger?.warn('Using registry at', BOWER_REGISTRY_CONFIG.register)
try {
// TODO: npm implementation
const bowerJSONPath = path.join(cwd, 'bower.json')
const hasBowerJSON = fs.existsSync(bowerJSONPath)

Expand Down Expand Up @@ -108,6 +109,7 @@ async function confirm (properties) {
async function exists (BOWER_REGISTRY_CONFIG, plugin) {
const pluginName = plugin.toString().toLowerCase()
return new Promise((resolve, reject) => {
// TODO: npm implementation
bower.commands.search(pluginName, {
registry: BOWER_REGISTRY_CONFIG.register
})
Expand All @@ -121,6 +123,7 @@ async function exists (BOWER_REGISTRY_CONFIG, plugin) {

async function registerWithBowerRepo (BOWER_REGISTRY_CONFIG, plugin, repository) {
return new Promise((resolve, reject) => {
// TODO: npm implementation
bower.commands.register(plugin.toString(), repository.url || repository, {
registry: BOWER_REGISTRY_CONFIG
})
Expand Down
1 change: 1 addition & 0 deletions lib/integration/PluginManagement/rename.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ async function renameInBowerRepo ({
async function exists (BOWER_REGISTRY_CONFIG, plugin) {
const pluginName = plugin.toString().toLowerCase()
return new Promise((resolve, reject) => {
// TODO: npm implementation
bower.commands.search(pluginName, {
registry: BOWER_REGISTRY_CONFIG.register
})
Expand Down
19 changes: 17 additions & 2 deletions lib/integration/PluginManagement/uninstall.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { createPromptTask } from '../../util/createPromptTask.js'
import { errorPrinter, packageNamePrinter } from './print.js'
import { intersection } from 'lodash-es'
import path from 'path'
import { uninstall as npmUninstall } from './npm.js'

export default async function uninstall ({
plugins,
Expand All @@ -24,11 +25,25 @@ export default async function uninstall ({
if (!targets?.length) return targets

await loadPluginData({ logger, targets })
const uninstallTargetsToBeUninstalled = targets.filter(target => target.isToBeUninstalled)
await eachOfLimitProgress(
targets.filter(target => target.isToBeUninstalled),
uninstallTargetsToBeUninstalled,
target => target.uninstall(),
percentage => logger?.logProgress?.(`${chalk.bold.cyan('<info>')} Uninstalling plugins ${percentage}% complete`)
percentage => logger?.logProgress?.(`${chalk.bold.cyan('<info>')} Uninstalling plugins ${percentage / (project.isNPM ? 2 : 1)}% complete`)
)
if (project.isNPM) {
// Batch uninstall npm plugins as it's faster
const installArgs = uninstallTargetsToBeUninstalled
.filter(target => target.isNPMUninstall)
.map(target => `${target.packageName}`)
const outputPath = path.join(cwd, 'src')
await npmUninstall({ logger, cwd: outputPath, args: installArgs })
await eachOfLimitProgress(
uninstallTargetsToBeUninstalled,
target => target.postUninstall(),
percentage => logger?.logProgress?.(`${chalk.bold.cyan('<info>')} Uninstalling plugins ${50 + (percentage / 2)}% complete`)
)
}
logger?.log(`${chalk.bold.cyan('<info>')} Uninstalling plugins 100% complete`)
const installedDependencies = await project.getInstalledDependencies()
await updateManifest({ project, targets, installedDependencies, isInteractive })
Expand Down
1 change: 1 addition & 0 deletions lib/integration/PluginManagement/unregister.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export default async function unregister ({
const BOWER_REGISTRY_CONFIG = getBowerRegistryConfig({ cwd })
logger?.warn('Using registry at', BOWER_REGISTRY_CONFIG.register)
try {
// TODO: npm implementation
const bowerJSONPath = path.join(cwd, 'bower.json')
const hasBowerJSON = fs.existsSync(bowerJSONPath)
const bowerJSON = hasBowerJSON ? await readValidateJSON(bowerJSONPath) : {}
Expand Down
16 changes: 15 additions & 1 deletion lib/integration/PluginManagement/update.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import Project from '../Project.js'
import { createPromptTask } from '../../util/createPromptTask.js'
import { errorPrinter, packageNamePrinter, versionPrinter, existingVersionPrinter } from './print.js'
import { eachOfLimitProgress, eachOfSeriesProgress } from '../../util/promises.js'
import { update as npmUpdate } from './npm.js'
/** @typedef {import("../Target.js").default} Target */

export default async function update ({
Expand Down Expand Up @@ -35,8 +36,21 @@ export default async function update ({
await eachOfSeriesProgress(
updateTargetsToBeUpdated,
target => target.update(),
percentage => logger?.logProgress?.(`${chalk.bold.cyan('<info>')} Updating plugins ${percentage}% complete`)
percentage => logger?.logProgress?.(`${chalk.bold.cyan('<info>')} Updating plugins ${percentage / (project.isNPM ? 2 : 1)}% complete`)
)
if (project.isNPM) {
// Batch update npm plugins as it's faster
const installArgs = updateTargetsToBeUpdated
.filter(target => target.isNPMUpdate)
.map(target => `${target.packageName}`)
const outputPath = path.join(cwd, 'src')
await npmUpdate({ logger, cwd: outputPath, args: installArgs })
await eachOfSeriesProgress(
updateTargetsToBeUpdated,
target => target.postUpdate(),
percentage => logger?.logProgress?.(`${chalk.bold.cyan('<info>')} Updating plugins ${50 + (percentage / 2)}% complete`)
)
}
logger?.log(`${chalk.bold.cyan('<info>')} Updating plugins 100% complete`)
}
await summariseUpdates({ logger, targets })
Expand Down
11 changes: 9 additions & 2 deletions lib/integration/Project.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ export default class Project {
}
}

isNPM () {
return fs.existsSync(path.join(this.cwd, 'src/package.json'))
}

tryThrowInvalidPath () {
if (this.containsManifestFile) return
this.logger?.error('Fatal error: please run above commands in adapt course directory.')
Expand Down Expand Up @@ -82,9 +86,12 @@ export default class Project {

async getInstalledDependencies () {
const getDependencyBowerJSONs = async () => {
const glob = `${this.cwd.replace(/\\/g, '/')}/src/**/bower.json`
const globs = [
this.isNPM && `${this.cwd.replace(/\\/g, '/')}/src/node_modules/adapt-*/package.json`,
!this.isNPM && `${this.cwd.replace(/\\/g, '/')}/src/*/adapt-*/bower.json`
].filter(Boolean)
const bowerJSONPaths = await new Promise((resolve, reject) => {
globs(glob, (err, matches) => {
globs(globs, (err, matches) => {
if (err) return reject(err)
resolve(matches)
})
Expand Down
Loading