run-selfhosted.js 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. // surrounding_box function
  2. //
  3. // It's really hard to see an error message without using
  4. // the surrounding_box function to highlight its location.
  5. // The implementation of this in packages/backend might not
  6. // work in older versions of node, so we instead re-implement
  7. // it here.
  8. const surrounding_box = (col, lines) => {
  9. const lengths = lines.map(line => line.length);
  10. const max_length = Math.max(...lengths);
  11. const c = str => `\x1b[${col}m${str}\x1b[0m`;
  12. const bar = c(Array(max_length + 4).fill('━').join(''));
  13. for ( let i = 0 ; i < lines.length ; i++ ) {
  14. while ( lines[i].length < max_length ) {
  15. lines[i] += ' ';
  16. }
  17. lines[i] = `${c('┃ ')} ${lines[i]} ${c(' ┃')}`;
  18. }
  19. lines.unshift(`${c('┏')}${bar}${c('┓')}`);
  20. lines.push(`${c('┗')}${bar}${c('┛')}`);
  21. };
  22. // node version check
  23. {
  24. // Keeping track of WHY certain versions don't work
  25. const ver_info = [
  26. { under: 14, reasons: ['optional chaining is not available'] },
  27. { under: 16, reasons: ['diskusage package ABI mismatch'] },
  28. ];
  29. const lowest_allowed = Math.max(...ver_info.map(r => r.under));
  30. // ACTUAL VERSION CHECK
  31. const [major, minor] = process.versions.node.split('.').map(Number);
  32. if ( major < lowest_allowed ) {
  33. const lines = [];
  34. lines.push(`Please use a version of Node.js ${lowest_allowed} or newer.`);
  35. lines.push(`Issues with node ${process.versions.node}:`);
  36. // We also show the user the reasons in case they want to know
  37. for ( const { under, reasons } of ver_info ) {
  38. if ( major < under ) {
  39. lines.push(` - ${reasons.join(', ')}`);
  40. }
  41. }
  42. surrounding_box('31;1', lines);
  43. console.error(lines.join('\n'));
  44. process.exit(1);
  45. }
  46. }
  47. const main = async () => {
  48. const {
  49. Kernel,
  50. CoreModule,
  51. DatabaseModule,
  52. PuterDriversModule,
  53. LocalDiskStorageModule,
  54. SelfhostedModule
  55. } = (await import('@heyputer/backend')).default;
  56. console.log('kerne', Kernel);
  57. const k = new Kernel();
  58. k.add_module(new CoreModule());
  59. k.add_module(new DatabaseModule());
  60. k.add_module(new PuterDriversModule());
  61. k.add_module(new LocalDiskStorageModule());
  62. k.add_module(new SelfhostedModule()),
  63. k.boot();
  64. };
  65. const early_init_errors = [
  66. {
  67. text: `Cannot find package '@heyputer/backend'`,
  68. notes: [
  69. 'this usually happens if you forget `npm install`'
  70. ],
  71. suggestions: [
  72. 'try running `npm install`'
  73. ],
  74. technical_notes: [
  75. '@heyputer/backend is in an npm workspace'
  76. ]
  77. },
  78. {
  79. text: `Cannot find package`,
  80. notes: [
  81. 'this usually happens if you forget `npm install`'
  82. ],
  83. suggestions: [
  84. 'try running `npm install`'
  85. ],
  86. }
  87. ];
  88. const newstuff = {
  89. // Nullish coalescing operator
  90. nco: (...a) => a.reduce((acc, val) => acc == undefined ? val : acc),
  91. // Optional chaining
  92. oc: (obj, ...keys) => keys.reduce((acc, key) => acc ? acc[key] : undefined, obj),
  93. oc_call: (maybe_fn, ...args) => maybe_fn ? maybe_fn(...args) : undefined,
  94. };1
  95. const _print_error_help = (error_help) => {
  96. const lines = [];
  97. lines.push(nco(error_help.title, error_help.text));
  98. for ( const note of (nco(error_help.notes, [])) ) {
  99. lines.push(`📝 ${note}`)
  100. }
  101. if ( error_help.suggestions ) {
  102. lines.push('Suggestions:');
  103. for ( const suggestion of error_help.suggestions ) {
  104. lines.push(`- ${suggestion}`);
  105. }
  106. }
  107. if ( error_help.technical_notes ) {
  108. lines.push('Technical Notes:');
  109. for ( const note of error_help.technical_notes ) {
  110. lines.push(`- ${note}`);
  111. }
  112. }
  113. surrounding_box('31;1', lines);
  114. console.error(lines.join('\n'));
  115. }
  116. (async () => {
  117. try {
  118. await main();
  119. } catch (e) {
  120. for ( const error_help of early_init_errors ) {
  121. if ( oc_call(oc(e, message, includes), error_help.text) ) {
  122. _print_error_help(error_help);
  123. break;
  124. }
  125. }
  126. throw e;
  127. }
  128. })();