winget.js 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. const crypto = require('crypto');
  2. const fs = require('fs');
  3. const http = require('http');
  4. const https = require('https');
  5. const path = require('path');
  6. const manifestDir = process.argv[2];
  7. const configuration = require('../package.json');
  8. const builder = fs.readFileSync('./electron-builder.yml', 'utf-8');
  9. const get = (url, timeout) => {
  10. return new Promise((resolve, reject) => {
  11. const httpModule = url.split(':').shift() === 'https' ? https : http;
  12. const request = httpModule.request(url, {}, (response) => {
  13. if (response.statusCode === 200) {
  14. const data = [];
  15. let position = 0;
  16. response.on('data', (chunk) => {
  17. data.push(chunk);
  18. position += chunk.length;
  19. process.stdout.write(' ' + position + ' bytes\r');
  20. });
  21. response.on('err', (err) => {
  22. reject(err);
  23. });
  24. response.on('end', () => {
  25. resolve(Buffer.concat(data));
  26. });
  27. }
  28. else if (response.statusCode === 302) {
  29. get(response.headers.location).then((data) => {
  30. resolve(data);
  31. }).catch((err) => {
  32. reject(err);
  33. });
  34. }
  35. else {
  36. const err = new Error("The web request failed with status code " + response.statusCode + " at '" + url + "'.");
  37. err.type = 'error';
  38. err.url = url;
  39. err.status = response.statusCode;
  40. reject(err);
  41. }
  42. });
  43. request.on("error", (err) => {
  44. reject(err);
  45. });
  46. if (timeout) {
  47. request.setTimeout(timeout, () => {
  48. request.destroy();
  49. const err = new Error("The web request timed out at '" + url + "'.");
  50. err.type = 'timeout';
  51. err.url = url;
  52. reject(err);
  53. });
  54. }
  55. request.end();
  56. });
  57. };
  58. const name = configuration.name;
  59. const version = configuration.version;
  60. const productName = configuration.productName;
  61. const publisher = configuration.author.name;
  62. const packageIdentifier = publisher.replace(' ', '') + '.' + productName;
  63. const license = 'Copyright (c) ' + publisher;
  64. const repository = 'https://github.com/' + configuration.repository;
  65. const url = repository + '/releases/download/v' + version + '/' + productName + '-Setup-' + version + '.exe';
  66. const extensions = builder.split('\n').filter((line) => line.startsWith(' ext')).map((line) => / {4}ext: (.*)\s*/.exec(line)[1]).sort().map((extension) => '- ' + extension).join('\n');
  67. get(url).then((data) => {
  68. const sha256 = crypto.createHash('sha256').update(data).digest('hex').toUpperCase();
  69. const versionDir = path.join(manifestDir, publisher[0].toLowerCase(), publisher.replace(' ', ''), productName, version);
  70. if (!fs.existsSync(versionDir)){
  71. fs.mkdirSync(versionDir, { recursive: true });
  72. }
  73. const manifestFile = path.join(versionDir, packageIdentifier);
  74. fs.writeFileSync(manifestFile + '.yaml', [
  75. 'PackageIdentifier: ' + packageIdentifier,
  76. 'PackageVersion: ' + version,
  77. 'DefaultLocale: en-US',
  78. 'ManifestType: version',
  79. 'ManifestVersion: 1.0.0',
  80. ''
  81. ].join('\n'));
  82. fs.writeFileSync(manifestFile + '.installer.yaml', [
  83. 'PackageIdentifier: ' + packageIdentifier,
  84. 'PackageVersion: ' + version,
  85. 'Platform:',
  86. '- Windows.Desktop',
  87. 'InstallModes:',
  88. '- silent',
  89. '- silentWithProgress',
  90. 'Installers:',
  91. '- Architecture: x86',
  92. ' Scope: user',
  93. ' InstallerType: nullsoft',
  94. ' InstallerUrl: ' + url,
  95. ' InstallerSha256: ' + sha256,
  96. ' InstallerLocale: en-US',
  97. ' InstallerSwitches:',
  98. ' Custom: /NORESTART',
  99. ' UpgradeBehavior: install',
  100. '- Architecture: arm64',
  101. ' Scope: user',
  102. ' InstallerType: nullsoft',
  103. ' InstallerUrl: ' + url,
  104. ' InstallerSha256: ' + sha256,
  105. ' InstallerLocale: en-US',
  106. ' InstallerSwitches:',
  107. ' Custom: /NORESTART',
  108. ' UpgradeBehavior: install',
  109. 'FileExtensions:',
  110. extensions,
  111. 'ManifestType: installer',
  112. 'ManifestVersion: 1.0.0',
  113. ''
  114. ].join('\n'));
  115. fs.writeFileSync(manifestFile + '.locale.en-US.yaml', [
  116. 'PackageIdentifier: ' + packageIdentifier,
  117. 'PackageVersion: ' + version,
  118. 'PackageName: ' + productName,
  119. 'PackageLocale: en-US',
  120. 'PackageUrl: ' + repository,
  121. 'Publisher: ' + publisher,
  122. 'PublisherUrl: ' + repository,
  123. 'PublisherSupportUrl: ' + repository + '/issues',
  124. 'Author: ' + publisher,
  125. 'License: ' + license,
  126. 'Copyright: ' + license,
  127. 'CopyrightUrl: ' + repository + '/blob/main/LICENSE',
  128. 'ShortDescription: ' + configuration.description,
  129. 'Description: ' + configuration.description,
  130. 'Moniker: ' + name,
  131. 'Tags:',
  132. '- machine-learning',
  133. '- deep-learning',
  134. '- neural-network',
  135. 'ManifestType: defaultLocale',
  136. 'ManifestVersion: 1.0.0',
  137. ''
  138. ].join('\n'));
  139. }).catch((err) => {
  140. console.log(err.message);
  141. });