Ei kuvausta
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

pbts.js 6.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. "use strict";
  2. var child_process = require("child_process"),
  3. path = require("path"),
  4. fs = require("fs"),
  5. pkg = require("./package.json"),
  6. util = require("./util");
  7. util.setup();
  8. var minimist = require("minimist"),
  9. chalk = require("chalk"),
  10. glob = require("glob"),
  11. tmp = require("tmp");
  12. /**
  13. * Runs pbts programmatically.
  14. * @param {string[]} args Command line arguments
  15. * @param {function(?Error, string=)} [callback] Optional completion callback
  16. * @returns {number|undefined} Exit code, if known
  17. */
  18. exports.main = function(args, callback) {
  19. var argv = minimist(args, {
  20. alias: {
  21. name: "n",
  22. out : "o",
  23. main: "m",
  24. global: "g",
  25. import: "i"
  26. },
  27. string: [ "name", "out", "global", "import" ],
  28. boolean: [ "comments", "main" ],
  29. default: {
  30. comments: true,
  31. main: false
  32. }
  33. });
  34. var files = argv._;
  35. if (!files.length) {
  36. if (callback)
  37. callback(Error("usage")); // eslint-disable-line callback-return
  38. else
  39. process.stderr.write([
  40. "protobuf.js v" + pkg.version + " CLI for TypeScript",
  41. "",
  42. chalk.bold.white("Generates TypeScript definitions from annotated JavaScript files."),
  43. "",
  44. " -o, --out Saves to a file instead of writing to stdout.",
  45. "",
  46. " -g, --global Name of the global object in browser environments, if any.",
  47. "",
  48. " -i, --import Comma delimited list of imports. Local names will equal camelCase of the basename.",
  49. "",
  50. " --no-comments Does not output any JSDoc comments.",
  51. "",
  52. chalk.bold.gray(" Internal flags:"),
  53. "",
  54. " -n, --name Wraps everything in a module of the specified name.",
  55. "",
  56. " -m, --main Whether building the main library without any imports.",
  57. "",
  58. "usage: " + chalk.bold.green("pbts") + " [options] file1.js file2.js ..." + chalk.bold.gray(" (or) ") + "other | " + chalk.bold.green("pbts") + " [options] -",
  59. ""
  60. ].join("\n"));
  61. return 1;
  62. }
  63. // Resolve glob expressions
  64. for (var i = 0; i < files.length;) {
  65. if (glob.hasMagic(files[i])) {
  66. var matches = glob.sync(files[i]);
  67. Array.prototype.splice.apply(files, [i, 1].concat(matches));
  68. i += matches.length;
  69. } else
  70. ++i;
  71. }
  72. var cleanup = [];
  73. // Read from stdin (to a temporary file)
  74. if (files.length === 1 && files[0] === "-") {
  75. var data = [];
  76. process.stdin.on("data", function(chunk) {
  77. data.push(chunk);
  78. });
  79. process.stdin.on("end", function() {
  80. files[0] = tmp.tmpNameSync() + ".js";
  81. fs.writeFileSync(files[0], Buffer.concat(data));
  82. cleanup.push(files[0]);
  83. callJsdoc();
  84. });
  85. // Load from disk
  86. } else {
  87. callJsdoc();
  88. }
  89. function callJsdoc() {
  90. // There is no proper API for jsdoc, so this executes the CLI and pipes the output
  91. var basedir = path.join(__dirname, ".");
  92. var moduleName = argv.name || "null";
  93. var nodePath = process.execPath;
  94. var cmd = "\"" + nodePath + "\" \"" + require.resolve("jsdoc/jsdoc.js") + "\" -c \"" + path.join(basedir, "lib", "tsd-jsdoc.json") + "\" -q \"module=" + encodeURIComponent(moduleName) + "&comments=" + Boolean(argv.comments) + "\" " + files.map(function(file) { return "\"" + file + "\""; }).join(" ");
  95. var child = child_process.exec(cmd, {
  96. cwd: process.cwd(),
  97. argv0: "node",
  98. stdio: "pipe",
  99. maxBuffer: 1 << 24 // 16mb
  100. });
  101. var out = [];
  102. var ended = false;
  103. var closed = false;
  104. child.stdout.on("data", function(data) {
  105. out.push(data);
  106. });
  107. child.stdout.on("end", function() {
  108. if (closed) finish();
  109. else ended = true;
  110. });
  111. child.stderr.pipe(process.stderr);
  112. child.on("close", function(code) {
  113. // clean up temporary files, no matter what
  114. try { cleanup.forEach(fs.unlinkSync); } catch(e) {/**/} cleanup = [];
  115. if (code) {
  116. out = out.join("").replace(/\s*JSDoc \d+\.\d+\.\d+ [^$]+/, "");
  117. process.stderr.write(out);
  118. var err = Error("code " + code);
  119. if (callback)
  120. return callback(err);
  121. throw err;
  122. }
  123. if (ended) return finish();
  124. closed = true;
  125. return undefined;
  126. });
  127. function getImportName(importItem) {
  128. return path.basename(importItem, ".js").replace(/([-_~.+]\w)/g, function(match) {
  129. return match[1].toUpperCase();
  130. });
  131. }
  132. function finish() {
  133. var output = [];
  134. if (argv.main)
  135. output.push(
  136. "// DO NOT EDIT! This is a generated file. Edit the JSDoc in src/*.js instead and run 'npm run types'.",
  137. ""
  138. );
  139. if (argv.global)
  140. output.push(
  141. "export as namespace " + argv.global + ";",
  142. ""
  143. );
  144. if (!argv.main) {
  145. // Ensure we have a usable array of imports
  146. var importArray = typeof argv.import === "string" ? argv.import.split(",") : argv.import || [];
  147. // Build an object of imports and paths
  148. var imports = {
  149. $protobuf: "protobufjs"
  150. };
  151. importArray.forEach(function(importItem) {
  152. imports[getImportName(importItem)] = importItem;
  153. });
  154. // Write out the imports
  155. Object.keys(imports).forEach(function(key) {
  156. output.push("import * as " + key + " from \"" + imports[key] + "\";");
  157. });
  158. }
  159. output = output.join("\n") + "\n" + out.join("");
  160. try {
  161. if (argv.out)
  162. fs.writeFileSync(argv.out, output, { encoding: "utf8" });
  163. else if (!callback)
  164. process.stdout.write(output, "utf8");
  165. return callback
  166. ? callback(null, output)
  167. : undefined;
  168. } catch (err) {
  169. if (callback)
  170. return callback(err);
  171. throw err;
  172. }
  173. }
  174. }
  175. return undefined;
  176. };