#! /usr/bin/env node
/**
* Script to run wiremock based on specific stub jar downloaded from local machine or if not found from nexus.
*
* Download sources:
* 1) local machine .m2 repository
* 2) nexus artifactory
*
* Required params:
* stubs - path to direct stubs jar link
* uk/co/hl/bf/working-day-calendar/0.2.9-SNAPSHOT/working-day-calendar-0.2.9-20180112.122824-2-stubs.jar
* port - port of wiremock to serve mocks
* 9000
*
* Example of use in project package.json:
* node ./mock/mock-backend.js stubs=uk/co/hl/bf/working-day-calendar/0.2.9-SNAPSHOT/working-day-calendar-0.2.9-20180112.122824-2-stubs.jar port=9000"
*/
const NPMRC_CA_PARAM_NAME = "ca";
const MAVEN_REPO = "https://nexus.hltech.dev/repository/maven-public/";
const fs = require('fs');
const request = require('request');
const unzip = require('unzip');
const execSync = require('child_process').execSync;
const dir = './stubs';
const jarDir = dir + '/stubs.jar';
const mappingsDir = dir + '/mappings';
cleanStubs(dir);
createBaseStubFolder();
downloadStubsJarAndRunWireMock(getParam('stubs'));
function downloadStubsJarAndRunWireMock(stubsPath) {
createJarFromLocalM2Source(
stubsPath,
createJarFromNexusSource
)
}
function createJarFromLocalM2Source(stubsPath, alternative) {
const pathToPackage = getUserHome() + '/.m2/repository/' + stubsPath;
console.log("Looking for jar in local", pathToPackage);
fs.readFile(pathToPackage, (err, data) => {
if (err) {
alternative(stubsPath);
return
}
fs.writeFile(jarDir, data, (err) => {
if (err) {
alternative(stubsPath);
return
}
runWireMockOnJustCreatedJar();
});
})
}
function createJarFromNexusSource(stubsPath) {
const projectCa = getNpmrcParam(NPMRC_CA_PARAM_NAME);
const ca = projectCa !== undefined ? {ca: projectCa} : {};
const pathToPackage = MAVEN_REPO + stubsPath;
console.log("Looking for jar in nexus", pathToPackage);
request({
method: "GET",
uri: pathToPackage,
agentOptions: ca
}, function(body, err) {
if (err) {
console.log('Jar downloading status: ' + err.statusCode + ' - ' + err.statusMessage);
} else {
console.log(body);
}
runWireMockOnJustCreatedJar();
}).pipe(fs.createWriteStream(jarDir));
}
function runWireMockOnJustCreatedJar() {
console.log("Running wiremock jar..");
extractStubsJar();
runWireMock(getParam('port'));
}
function createBaseStubFolder() {
if (!fs.existsSync(dir)){
fs.mkdirSync(dir);
}
if (!fs.existsSync(mappingsDir)){
fs.mkdirSync(mappingsDir);
}
}
function extractStubsJar() {
fs.createReadStream(jarDir)
.pipe(unzip.Parse())
.on('entry', function (entry) {
const fileName = entry.path;
if (fileName.endsWith(".json")) {
const filenameWithoutFolders = fileName.replace(/^.*[\\\/]/, '');
console.log("found", filenameWithoutFolders);
entry.pipe(fs.createWriteStream(mappingsDir + '/' + filenameWithoutFolders));
} else {
entry.autodrain();
}
});
}
function cleanStubs(path) {
const deleteFolderRecursive = function(path) {
if( fs.existsSync(path) ) {
fs.readdirSync(path).forEach(function(file,index){
const curPath = path + "/" + file;
if(fs.lstatSync(curPath).isDirectory()) { // recurse
deleteFolderRecursive(curPath);
} else {
fs.unlinkSync(curPath);
}
});
fs.rmdirSync(path);
}
};
deleteFolderRecursive(path);
}
function runWireMock(port) {
const spawn = require('child_process').spawn;
spawn('java', ['-jar', './mock/wiremock-standalone-2.14.0.jar', '--root-dir=' + dir, '--port=' + port], { stdio: 'inherit' });
}
function getUserHome() {
return process.env.HOME || process.env.USERPROFILE;
}
function getParam(key) {
for (i = 0; i < process.argv.length; i++) {
const val = process.argv[i];
const name = val.split('=')[0];
if (name === key) {
return val.split('=')[1];
}
}
console.log("Missing param: " + key);
process.exit(-1);
}
function getNpmrcParam(param) {
const paramValue = execSync('npm config get ' + param);
return paramValue.toString();
}
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="gatsby-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,
root,
}) => {
// 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,
root,
}),
`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 }) => {
const NPMRCPath = path.join(pathToPackage, `.npmrc`)
fs.outputFileSync(NPMRCPath, NPMRCContent)
return registerCleanupTask(() => {
fs.removeSync(NPMRCPath)
})
}
const publishPackage = async ({
packageName,
packagesToPublish,
root,
versionPostFix,
ignorePackageJSONChanges,
}) => {
const monoRepoPackageJsonPath = getMonorepoPackageJsonPath({
packageName,
root,
})
const { unadjustPackageJson, newPackageVersion } = adjustPackageJson({
monoRepoPackageJsonPath,
packageName,
root,
versionPostFix,
packagesToPublish,
ignorePackageJSONChanges,
})
const pathToPackage = path.dirname(monoRepoPackageJsonPath)
const uncreateTemporaryNPMRC = createTemporaryNPMRC({ pathToPackage })
// npm publish
const publishCmd = [
`npm`,
[`publish`, `--tag`, `gatsby-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