publisher.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407
  1. // Dependecies.
  2. const prompt = require('prompt');
  3. const shelljs = require('shelljs');
  4. const fs = require('fs-extra');
  5. const path = require('path');
  6. const rmDir = require("../NodeHelpers/rmDir");
  7. const colorConsole = require("../NodeHelpers/colorConsole");
  8. // CMD Arguments Management.
  9. let doNotBuild = false;
  10. let doNotPublish = false;
  11. // Pathe management.
  12. process.env.PATH += (path.delimiter + path.join(__dirname, 'node_modules', '.bin'));
  13. // Global Variables.
  14. const config = require("../gulp/config.json");
  15. const modules = config.modules.concat(config.viewerModules);
  16. const basePath = config.build.outputDirectory;
  17. const tempPath = config.build.tempDirectory + "packageES6/";
  18. const coreSrc = config.core.build.srcDirectory;
  19. const enginePath = coreSrc + "Engines/engine.ts";
  20. /**
  21. * Get Files from folder.
  22. */
  23. const getFiles = function(dir, files_) {
  24. files_ = files_ || [];
  25. var files = fs.readdirSync(dir);
  26. for (var i in files) {
  27. var name = dir + '/' + files[i];
  28. if (fs.statSync(name).isDirectory()) {
  29. getFiles(name, files_);
  30. } else {
  31. files_.push(name);
  32. }
  33. }
  34. return files_;
  35. }
  36. /**
  37. * Update the version in the engine class for Babylon
  38. */
  39. function updateEngineVersion(newVersion) {
  40. colorConsole.log("Updating version in engine.ts to: " + newVersion.green);
  41. let engineContent = fs.readFileSync(enginePath).toString();
  42. let replaced = engineContent.replace(/(public static get Version\(\): string {\s*return ")(.*)(";\s*})/g, "$1" + newVersion + "$3");
  43. fs.writeFileSync(enginePath, replaced);
  44. colorConsole.emptyLine();
  45. }
  46. /**
  47. * Get the version from the engine class for Babylon
  48. */
  49. function getEngineVersion() {
  50. colorConsole.log("Get version from engine.ts");
  51. const engineContent = fs.readFileSync(enginePath).toString();
  52. const versionRegex = new RegExp(`public static get Version\\(\\): string {[\\s\\S]*return "([\\s\\S]*?)";[\\s\\S]*}`, "gm");
  53. const match = versionRegex.exec(engineContent);
  54. if (match && match.length) {
  55. const version = match[1];
  56. colorConsole.log("Version found: " + version.green);
  57. colorConsole.emptyLine();
  58. return version;
  59. }
  60. colorConsole.error("Version not found in engine.ts");
  61. process.exit(1);
  62. }
  63. /**
  64. * Publish a package to npm.
  65. */
  66. function publish(version, packageName, basePath) {
  67. colorConsole.log(' Publishing ' + packageName.blue.bold + " from " + basePath.cyan);
  68. let tag = "";
  69. // check for alpha or beta
  70. if (version.indexOf('alpha') !== -1 || version.indexOf('beta') !== -1) {
  71. tag = '--tag preview';
  72. }
  73. //publish the respected package
  74. if (doNotPublish) {
  75. colorConsole.log(" If publishing enabled: " + ('npm publish \"' + basePath + "\"" + ' ' + tag).yellow);
  76. }
  77. else {
  78. colorConsole.log(" Executing: " + ('npm publish \"' + basePath + "\"" + ' ' + tag).bold);
  79. shelljs.exec('npm publish \"' + basePath + "\"" + ' ' + tag);
  80. }
  81. colorConsole.success(' Publishing ' + "OK".green);
  82. }
  83. /**
  84. * Build the folder with Gulp.
  85. */
  86. function buildBabylonJSAndDependencies() {
  87. colorConsole.log("Running gulp compilation");
  88. let exec = shelljs.exec("gulp typescript-libraries --gulpfile ../Gulp/gulpfile.js");
  89. if (exec.code) {
  90. colorConsole.error("Error during compilation, aborting");
  91. process.exit(1);
  92. }
  93. }
  94. /**
  95. * Process ES6 Packages.
  96. */
  97. function processEs6Packages(version) {
  98. modules.forEach(moduleName => {
  99. let module = config[moduleName];
  100. let es6Config = module.build.es6;
  101. if (!es6Config) {
  102. return;
  103. }
  104. colorConsole.log("Process " + "ES6".magenta + " Package: " + moduleName.blue.bold);
  105. let projectPath = es6Config.tsFolder;
  106. let buildPath = path.normalize(tempPath + moduleName);
  107. let legacyPackageJson = require(module.build.packageJSON || basePath + module.build.distOutputDirectory + 'package.json');
  108. colorConsole.log(" Cleanup " + buildPath.cyan);
  109. rmDir(buildPath);
  110. let command = 'tsc -t es5 -m esNext -p ' + projectPath + ' --outDir ' + buildPath;
  111. colorConsole.log(" Executing " + command.yellow);
  112. let tscCompile = shelljs.exec(command);
  113. if (tscCompile.code !== 0) {
  114. throw new Error("Tsc compilation failed");
  115. }
  116. if (module.build.requiredFiles) {
  117. module.build.requiredFiles.forEach(file => {
  118. colorConsole.log(" Copy required file: ", file.cyan, (buildPath + '/' + path.basename(file)).cyan);
  119. fs.copySync(file, buildPath + '/' + path.basename(file));
  120. });
  121. }
  122. if (es6Config.requiredFiles) {
  123. es6Config.requiredFiles.forEach(file => {
  124. colorConsole.log(" Copy es6 required file: ", file.cyan, (buildPath + '/' + path.basename(file)).cyan);
  125. fs.copySync(file, buildPath + '/' + path.basename(file));
  126. });
  127. }
  128. let files = getFiles(buildPath).map(f => f.replace(buildPath + "/", "")).filter(f => f.indexOf("assets/") === -1);
  129. legacyPackageJson.name = es6Config.packageName;
  130. legacyPackageJson.version = version;
  131. legacyPackageJson.main = "index.js";
  132. legacyPackageJson.module = "index.js";
  133. legacyPackageJson.esnext = "index.js";
  134. legacyPackageJson.typings = "index.d.ts";
  135. legacyPackageJson.files = files;
  136. ["dependencies", "peerDependencies", "devDependencies"].forEach(key => {
  137. if (legacyPackageJson[key]) {
  138. let dependencies = legacyPackageJson[key];
  139. legacyPackageJson[key] = {};
  140. Object.keys(dependencies).forEach(packageName => {
  141. if (packageName.indexOf("babylonjs") !== -1) {
  142. colorConsole.log(" Checking Internal Dependency: " + packageName.cyan);
  143. let dependencyName = packageName;
  144. for (var moduleName of modules) {
  145. if (config[moduleName] && config[moduleName].build.processDeclaration && config[moduleName].build.processDeclaration.packageName === packageName) {
  146. if (config[moduleName].build.es6) {
  147. dependencyName = config[moduleName].build.es6.packageName;
  148. colorConsole.log(" Replace Dependency: " + packageName.cyan + " by " + dependencyName.cyan);
  149. break;
  150. }
  151. }
  152. }
  153. legacyPackageJson[key][dependencyName] = version;
  154. } else if (!module.isCore) {
  155. legacyPackageJson[key][packageName] = dependencies[packageName];
  156. }
  157. });
  158. }
  159. });
  160. fs.writeFileSync(buildPath + '/package.json', JSON.stringify(legacyPackageJson, null, 4));
  161. // Do not publish yet.
  162. // publish(version, es6Config.packageName, buildPath);
  163. colorConsole.emptyLine();
  164. });
  165. }
  166. /**
  167. * Process Legacy Packages.
  168. */
  169. function processLegacyPackages(version) {
  170. modules.forEach(moduleName => {
  171. let module = config[moduleName];
  172. colorConsole.log("Process " + "UMD".magenta + " Package: " + moduleName.blue.bold);
  173. if (moduleName === "core") {
  174. processLegacyCore(version);
  175. }
  176. else if (moduleName === "viewer") {
  177. processLegacyViewer(module, version);
  178. }
  179. else {
  180. let outputDirectory = module.build.legacyPackageOutputDirectory || basePath + module.build.distOutputDirectory;
  181. if (module.build.requiredFiles) {
  182. module.build.requiredFiles.forEach(file => {
  183. colorConsole.log(" Copy required file: ", file.cyan, (outputDirectory + '/' + path.basename(file)).cyan);
  184. fs.copySync(file, outputDirectory + '/' + path.basename(file));
  185. });
  186. }
  187. let packageJson = require(outputDirectory + 'package.json');
  188. packageJson.version = version;
  189. colorConsole.log(" Update package version to: " + version.green);
  190. if (packageJson.dependencies) {
  191. Object.keys(packageJson.dependencies).forEach(key => {
  192. if (key.indexOf("babylonjs") !== -1) {
  193. packageJson.dependencies[key] = version;
  194. }
  195. });
  196. }
  197. fs.writeFileSync(outputDirectory + 'package.json', JSON.stringify(packageJson, null, 4));
  198. publish(version, moduleName, outputDirectory);
  199. colorConsole.emptyLine();
  200. }
  201. });
  202. }
  203. /**
  204. * Special treatment for legacy viewer.
  205. */
  206. function processLegacyViewer(module, version) {
  207. let projectPath = '../../Viewer';
  208. let buildPath = projectPath + "/build/src/";
  209. if (module.build.requiredFiles) {
  210. module.build.requiredFiles.forEach(file => {
  211. colorConsole.log(" Copy required file: ", file.cyan, (buildPath + path.basename(file)).cyan);
  212. fs.copySync(file, buildPath + path.basename(file));
  213. });
  214. }
  215. // The viewer needs to be built using tsc on the viewer's main repository
  216. // build the viewer.
  217. colorConsole.log(" Executing " + ('tsc -p ' + projectPath).yellow);
  218. let tscCompile = shelljs.exec('tsc -p ' + projectPath);
  219. if (tscCompile.code !== 0) {
  220. throw new Error("tsc compilation failed");
  221. }
  222. let packageJson = require(buildPath + '/package.json');
  223. let files = getFiles(buildPath).map(f => f.replace(buildPath + "/", "")).filter(f => f.indexOf("assets/") === -1);
  224. packageJson.files = files;
  225. packageJson.version = version;
  226. packageJson.module = "index.js";
  227. packageJson.main = "babylon.viewer.js";
  228. packageJson.typings = "index.d.ts";
  229. fs.writeFileSync(buildPath + '/package.json', JSON.stringify(packageJson, null, 4));
  230. publish(version, "viewer", buildPath);
  231. colorConsole.emptyLine();
  232. }
  233. /**
  234. * Special treatment for legacy core.
  235. */
  236. function processLegacyCore(version) {
  237. let package = {
  238. "name": "core",
  239. "path": "/../../"
  240. };
  241. let packageJson = require('../../package.json');
  242. // make a temporary directory
  243. fs.ensureDirSync(basePath + '/package/');
  244. let files = [
  245. {
  246. path: basePath + "/babylon.d.ts",
  247. objectName: "babylon.d.ts"
  248. },
  249. {
  250. path: basePath + "/babylon.js",
  251. objectName: "babylon.js"
  252. },
  253. {
  254. path: basePath + "/babylon.max.js",
  255. objectName: "babylon.max.js"
  256. },
  257. {
  258. path: basePath + "/babylon.max.js.map",
  259. objectName: "babylon.max.js.map"
  260. },
  261. {
  262. path: basePath + "/Oimo.js",
  263. objectName: "Oimo.js"
  264. },
  265. {
  266. path: basePath + package.path + "readme.md",
  267. objectName: "readme.md"
  268. }
  269. ];
  270. //copy them to the package path
  271. files.forEach(file => {
  272. fs.copySync(file.path, basePath + '/package/' + file.objectName);
  273. });
  274. // update package.json
  275. packageJson.version = version;
  276. colorConsole.log(" Generating file list");
  277. let packageFiles = ["package.json"];
  278. files.forEach(file => {
  279. if (!file.isDir) {
  280. packageFiles.push(file.objectName);
  281. } else {
  282. //todo is it better to read the content and add it? leave it like that ATM
  283. packageFiles.push(file.objectName + "/index.js", file.objectName + "/index.d.ts", file.objectName + "/es6.js")
  284. }
  285. });
  286. colorConsole.log(" Updating package.json");
  287. packageJson.files = packageFiles;
  288. packageJson.main = "babylon.js";
  289. packageJson.typings = "babylon.d.ts";
  290. fs.writeFileSync(basePath + '/package/' + 'package.json', JSON.stringify(packageJson, null, 4));
  291. publish(version, package.name, basePath + '/package/');
  292. // remove package directory
  293. fs.removeSync(basePath + '/package/');
  294. // now update the main package.json
  295. packageJson.files = packageJson.files.map(file => {
  296. if (file !== 'package.json' && file !== 'readme.md') {
  297. return 'dist/preview release/' + file;
  298. } else {
  299. return file;
  300. }
  301. });
  302. packageJson.main = "dist/preview release/babylon.js";
  303. packageJson.typings = "dist/preview release/babylon.d.ts";
  304. fs.writeFileSync('../../package.json', JSON.stringify(packageJson, null, 4));
  305. colorConsole.emptyLine();
  306. }
  307. const createVersion = function(version) {
  308. // Prevent to build for test Cases.
  309. if (!doNotBuild) {
  310. buildBabylonJSAndDependencies();
  311. }
  312. // Create the packages and publish if needed.
  313. processLegacyPackages(version);
  314. // Do not publish es6 yet.
  315. doNotPublish = true;
  316. processEs6Packages(version);
  317. }
  318. /**
  319. * Main function driving the publication.
  320. */
  321. module.exports = function(noBuild, noPublish, askVersion) {
  322. doNotBuild = noBuild;
  323. doNotPublish = noPublish;
  324. if (askVersion) {
  325. prompt.start();
  326. prompt.get(['version'], function (err, result) {
  327. const version = result.version;
  328. // Update the engine version if needed.
  329. if (!version || !version.length) {
  330. colorConsole.error("New version required.");
  331. Process.exit(1);
  332. return;
  333. }
  334. updateEngineVersion(version);
  335. createVersion(version);
  336. // Invite user to tag with the new version.
  337. if (newVersion) {
  338. colorConsole.log("Done, please tag git with " + version);
  339. }
  340. });
  341. }
  342. else {
  343. const version = getEngineVersion();
  344. createVersion(version);
  345. }
  346. };