publisher.js 13 KB

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