@epic-web/workshop-utils 6.38.0 → 6.40.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,8 @@
1
+ export type Result = {
2
+ status: 'success';
3
+ } | {
4
+ status: 'error';
5
+ message: string;
6
+ };
7
+ export declare function launchEditor(pathList: string[] | string, lineNumber?: number, colNumber?: number): Promise<Result>;
8
+ //# sourceMappingURL=launch-editor.server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"launch-editor.server.d.ts","sourceRoot":"","sources":["../../src/launch-editor.server.ts"],"names":[],"mappings":"AAwRA,MAAM,MAAM,MAAM,GACf;IAAE,MAAM,EAAE,SAAS,CAAA;CAAE,GACrB;IAAE,MAAM,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAA;AACvC,wBAAsB,YAAY,CACjC,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,EAC3B,UAAU,GAAE,MAAU,EACtB,SAAS,GAAE,MAAU,GACnB,OAAO,CAAC,MAAM,CAAC,CAiLjB"}
@@ -0,0 +1,379 @@
1
+ // copied (and barely modified) from create-react-app:
2
+ // https://github.com/facebook/create-react-app/blob/d960b9e38c062584ff6cfb1a70e1512509a966e7/packages/react-dev-utils/launchEditor.js
3
+ import child_process from 'child_process';
4
+ import fs from 'fs';
5
+ import os from 'os';
6
+ import path from 'path';
7
+ import fsExtra from 'fs-extra';
8
+ import shellQuote from 'shell-quote';
9
+ import { getRelativePath } from './apps.server.js';
10
+ function readablePath(filePath = '') {
11
+ const relative = getRelativePath(filePath);
12
+ const name = path.basename(relative);
13
+ const dir = path.dirname(relative);
14
+ return `'${name}' from:\n'${dir}'`;
15
+ }
16
+ function isTerminalEditor(editor) {
17
+ switch (editor) {
18
+ case 'vim':
19
+ case 'emacs':
20
+ case 'nano':
21
+ return true;
22
+ }
23
+ return false;
24
+ }
25
+ // Map from full process name to binary that starts the process
26
+ // We can't just re-use full process name, because it will spawn a new instance
27
+ // of the app every time
28
+ const COMMON_EDITORS_OSX = {
29
+ '/Applications/Atom.app/Contents/MacOS/Atom': 'atom',
30
+ '/Applications/Atom Beta.app/Contents/MacOS/Atom Beta': '/Applications/Atom Beta.app/Contents/MacOS/Atom Beta',
31
+ '/Applications/Brackets.app/Contents/MacOS/Brackets': 'brackets',
32
+ '/Applications/Sublime Text.app/Contents/MacOS/Sublime Text': '/Applications/Sublime Text.app/Contents/SharedSupport/bin/subl',
33
+ '/Applications/Sublime Text Dev.app/Contents/MacOS/Sublime Text': '/Applications/Sublime Text Dev.app/Contents/SharedSupport/bin/subl',
34
+ '/Applications/Sublime Text 2.app/Contents/MacOS/Sublime Text 2': '/Applications/Sublime Text 2.app/Contents/SharedSupport/bin/subl',
35
+ '/Applications/Cursor.app/Contents/MacOS/Cursor': 'cursor',
36
+ '/Applications/Visual Studio Code.app/Contents/MacOS/Electron': 'code',
37
+ '/Applications/Visual Studio Code - Insiders.app/Contents/MacOS/Electron': 'code-insiders',
38
+ '/Applications/VSCodium.app/Contents/MacOS/Electron': 'vscodium',
39
+ '/Applications/AppCode.app/Contents/MacOS/appcode': '/Applications/AppCode.app/Contents/MacOS/appcode',
40
+ '/Applications/CLion.app/Contents/MacOS/clion': '/Applications/CLion.app/Contents/MacOS/clion',
41
+ '/Applications/IntelliJ IDEA.app/Contents/MacOS/idea': '/Applications/IntelliJ IDEA.app/Contents/MacOS/idea',
42
+ '/Applications/PhpStorm.app/Contents/MacOS/phpstorm': '/Applications/PhpStorm.app/Contents/MacOS/phpstorm',
43
+ '/Applications/PyCharm.app/Contents/MacOS/pycharm': '/Applications/PyCharm.app/Contents/MacOS/pycharm',
44
+ '/Applications/PyCharm CE.app/Contents/MacOS/pycharm': '/Applications/PyCharm CE.app/Contents/MacOS/pycharm',
45
+ '/Applications/RubyMine.app/Contents/MacOS/rubymine': '/Applications/RubyMine.app/Contents/MacOS/rubymine',
46
+ '/Applications/WebStorm.app/Contents/MacOS/webstorm': '/Applications/WebStorm.app/Contents/MacOS/webstorm',
47
+ '/Applications/MacVim.app/Contents/MacOS/MacVim': 'mvim',
48
+ '/Applications/GoLand.app/Contents/MacOS/goland': '/Applications/GoLand.app/Contents/MacOS/goland',
49
+ '/Applications/Rider.app/Contents/MacOS/rider': '/Applications/Rider.app/Contents/MacOS/rider',
50
+ '/Applications/Zed/Zed.app/Contents/MacOS/zed': 'zed',
51
+ };
52
+ const COMMON_EDITORS_LINUX = {
53
+ atom: 'atom',
54
+ Brackets: 'brackets',
55
+ cursor: 'cursor',
56
+ code: 'code',
57
+ 'code-insiders': 'code-insiders',
58
+ vscodium: 'vscodium',
59
+ emacs: 'emacs',
60
+ gvim: 'gvim',
61
+ 'idea.sh': 'idea',
62
+ 'phpstorm.sh': 'phpstorm',
63
+ 'pycharm.sh': 'pycharm',
64
+ 'rubymine.sh': 'rubymine',
65
+ sublime_text: 'sublime_text',
66
+ vim: 'vim',
67
+ 'webstorm.sh': 'webstorm',
68
+ 'goland.sh': 'goland',
69
+ 'rider.sh': 'rider',
70
+ zed: 'zed',
71
+ };
72
+ const COMMON_EDITORS_WIN = [
73
+ 'Brackets.exe',
74
+ 'Cursor.exe',
75
+ 'Code.exe',
76
+ 'Code - Insiders.exe',
77
+ 'VSCodium.exe',
78
+ 'atom.exe',
79
+ 'sublime_text.exe',
80
+ 'notepad++.exe',
81
+ 'clion.exe',
82
+ 'clion64.exe',
83
+ 'idea.exe',
84
+ 'idea64.exe',
85
+ 'phpstorm.exe',
86
+ 'phpstorm64.exe',
87
+ 'pycharm.exe',
88
+ 'pycharm64.exe',
89
+ 'rubymine.exe',
90
+ 'rubymine64.exe',
91
+ 'webstorm.exe',
92
+ 'webstorm64.exe',
93
+ 'goland.exe',
94
+ 'goland64.exe',
95
+ 'rider.exe',
96
+ 'rider64.exe',
97
+ 'zed.exe',
98
+ ];
99
+ // Transpiled version of: /^([A-Za-z]:[/\\])?[\p{L}0-9/.\-_\\]+$/u
100
+ // Non-transpiled version requires support for Unicode property regex. Allows
101
+ // alphanumeric characters, periods, dashes, slashes, and underscores.
102
+ const WINDOWS_FILE_NAME_WHITELIST = /^([A-Za-z]:[/\\])?(?:[\x2D-9A-Z\\_a-z\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0560-\u0588\u05D0-\u05EA\u05EF-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u0860-\u086A\u08A0-\u08B4\u08B6-\u08BD\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u09FC\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0AF9\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58-\u0C5A\u0C60\u0C61\u0C80\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D54-\u0D56\u0D5F-\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16F1-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1878\u1880-\u1884\u1887-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1C80-\u1C88\u1C90-\u1CBA\u1CBD-\u1CBF\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2183\u2184\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005\u3006\u3031-\u3035\u303B\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312F\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FEF\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6E5\uA717-\uA71F\uA722-\uA788\uA78B-\uA7B9\uA7F7-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA8FD\uA8FE\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uA9E0-\uA9E4\uA9E6-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB65\uAB70-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDE80-\uDE9C\uDEA0-\uDED0\uDF00-\uDF1F\uDF2D-\uDF40\uDF42-\uDF49\uDF50-\uDF75\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF]|\uD801[\uDC00-\uDC9D\uDCB0-\uDCD3\uDCD8-\uDCFB\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDCE0-\uDCF2\uDCF4\uDCF5\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00\uDE10-\uDE13\uDE15-\uDE17\uDE19-\uDE35\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE4\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48\uDC80-\uDCB2\uDCC0-\uDCF2\uDD00-\uDD23\uDF00-\uDF1C\uDF27\uDF30-\uDF45]|\uD804[\uDC03-\uDC37\uDC83-\uDCAF\uDCD0-\uDCE8\uDD03-\uDD26\uDD44\uDD50-\uDD72\uDD76\uDD83-\uDDB2\uDDC1-\uDDC4\uDDDA\uDDDC\uDE00-\uDE11\uDE13-\uDE2B\uDE80-\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA8\uDEB0-\uDEDE\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3D\uDF50\uDF5D-\uDF61]|\uD805[\uDC00-\uDC34\uDC47-\uDC4A\uDC80-\uDCAF\uDCC4\uDCC5\uDCC7\uDD80-\uDDAE\uDDD8-\uDDDB\uDE00-\uDE2F\uDE44\uDE80-\uDEAA\uDF00-\uDF1A]|\uD806[\uDC00-\uDC2B\uDCA0-\uDCDF\uDCFF\uDE00\uDE0B-\uDE32\uDE3A\uDE50\uDE5C-\uDE83\uDE86-\uDE89\uDE9D\uDEC0-\uDEF8]|\uD807[\uDC00-\uDC08\uDC0A-\uDC2E\uDC40\uDC72-\uDC8F\uDD00-\uDD06\uDD08\uDD09\uDD0B-\uDD30\uDD46\uDD60-\uDD65\uDD67\uDD68\uDD6A-\uDD89\uDD98\uDEE0-\uDEF2]|\uD808[\uDC00-\uDF99]|\uD809[\uDC80-\uDD43]|[\uD80C\uD81C-\uD820\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD811[\uDC00-\uDE46]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDED0-\uDEED\uDF00-\uDF2F\uDF40-\uDF43\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDE40-\uDE7F\uDF00-\uDF44\uDF50\uDF93-\uDF9F\uDFE0\uDFE1]|\uD821[\uDC00-\uDFF1]|\uD822[\uDC00-\uDEF2]|\uD82C[\uDC00-\uDD1E\uDD70-\uDEFB]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB]|\uD83A[\uDC00-\uDCC4\uDD00-\uDD43]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0]|\uD87E[\uDC00-\uDE1D])+$/;
103
+ function addWorkspaceToArgumentsIfExists(args, workspace) {
104
+ if (workspace) {
105
+ args.unshift(workspace);
106
+ }
107
+ return args;
108
+ }
109
+ function getArgumentsForLineNumber(editor, fileName, lineNumber, colNumber, workspace) {
110
+ const editorBasename = path.basename(editor).replace(/\.(exe|cmd|bat)$/i, '');
111
+ switch (editorBasename) {
112
+ case 'atom':
113
+ case 'Atom':
114
+ case 'Atom Beta':
115
+ case 'subl':
116
+ case 'sublime':
117
+ case 'sublime_text':
118
+ return [`${fileName}:${lineNumber}:${colNumber}`];
119
+ case 'wstorm':
120
+ case 'charm':
121
+ return [`${fileName}:${lineNumber}`];
122
+ case 'notepad++':
123
+ return [`-n${lineNumber}`, `-c${colNumber}`, fileName];
124
+ case 'vim':
125
+ case 'mvim':
126
+ case 'joe':
127
+ case 'gvim':
128
+ return [`+${lineNumber}`, fileName];
129
+ case 'emacs':
130
+ case 'emacsclient':
131
+ return [`+${lineNumber}:${colNumber}`, fileName];
132
+ case 'rmate':
133
+ case 'mate':
134
+ case 'mine':
135
+ return ['--line', lineNumber, fileName];
136
+ case 'cursor':
137
+ case 'code':
138
+ case 'Code':
139
+ case 'code-insiders':
140
+ case 'Code - Insiders':
141
+ case 'vscodium':
142
+ case 'VSCodium':
143
+ return addWorkspaceToArgumentsIfExists(['-g', `${fileName}:${lineNumber}:${colNumber}`], workspace);
144
+ case 'appcode':
145
+ case 'clion':
146
+ case 'clion64':
147
+ case 'idea':
148
+ case 'idea64':
149
+ case 'phpstorm':
150
+ case 'phpstorm64':
151
+ case 'pycharm':
152
+ case 'pycharm64':
153
+ case 'rubymine':
154
+ case 'rubymine64':
155
+ case 'webstorm':
156
+ case 'webstorm64':
157
+ case 'goland':
158
+ case 'goland64':
159
+ case 'rider':
160
+ case 'rider64':
161
+ return addWorkspaceToArgumentsIfExists(['--line', lineNumber.toString(), fileName], workspace);
162
+ }
163
+ // For all others, drop the lineNumber until we have
164
+ // a mapping above, since providing the lineNumber incorrectly
165
+ // can result in errors or confusing behavior.
166
+ return [fileName];
167
+ }
168
+ function guessEditor() {
169
+ // Explicit config always wins
170
+ if (process.env.EPICSHOP_EDITOR) {
171
+ return shellQuote.parse(process.env.EPICSHOP_EDITOR).map((a) => String(a));
172
+ }
173
+ // We can find out which editor is currently running by:
174
+ // `ps x` on macOS and Linux
175
+ // `Get-Process` on Windows
176
+ try {
177
+ if (process.platform === 'darwin') {
178
+ const output = child_process.execSync('ps x').toString();
179
+ const processNames = Object.keys(COMMON_EDITORS_OSX);
180
+ for (let i = 0; i < processNames.length; i++) {
181
+ const processName = processNames[i];
182
+ if (processName && output.includes(processName)) {
183
+ const editor = COMMON_EDITORS_OSX[processName];
184
+ return [editor];
185
+ }
186
+ }
187
+ }
188
+ else if (process.platform === 'win32') {
189
+ // Some processes need elevated rights to get its executable path.
190
+ // Just filter them out upfront. This also saves 10-20ms on the command.
191
+ const output = child_process
192
+ .execSync('wmic process where "executablepath is not null" get executablepath')
193
+ .toString();
194
+ const runningProcesses = output.split('\r\n');
195
+ for (let i = 0; i < runningProcesses.length; i++) {
196
+ const processPath = runningProcesses[i]?.trim();
197
+ if (!processPath)
198
+ continue;
199
+ const processName = path.basename(processPath);
200
+ if (COMMON_EDITORS_WIN.includes(processName)) {
201
+ return [processPath];
202
+ }
203
+ }
204
+ }
205
+ else if (process.platform === 'linux') {
206
+ // --no-heading No header line
207
+ // x List all processes owned by you
208
+ // -o comm Need only names column
209
+ const output = child_process
210
+ .execSync('ps x --no-heading -o comm --sort=comm')
211
+ .toString();
212
+ const processNames = Object.keys(COMMON_EDITORS_LINUX);
213
+ for (let i = 0; i < processNames.length; i++) {
214
+ const processName = processNames[i];
215
+ if (!processName)
216
+ continue;
217
+ if (output.includes(processName)) {
218
+ // @ts-expect-error 🤷‍♂️ it's fine
219
+ return [COMMON_EDITORS_LINUX[processName]];
220
+ }
221
+ }
222
+ }
223
+ }
224
+ catch {
225
+ // Ignore...
226
+ }
227
+ // Last resort, use old skool env vars
228
+ if (process.env.VISUAL) {
229
+ return [process.env.VISUAL];
230
+ }
231
+ else if (process.env.EDITOR) {
232
+ return [process.env.EDITOR];
233
+ }
234
+ return [null];
235
+ }
236
+ let _childProcess = null;
237
+ export async function launchEditor(pathList, lineNumber = 1, colNumber = 1) {
238
+ // Sanitize lineNumber to prevent malicious use on win32
239
+ // via: https://github.com/nodejs/node/blob/c3bb4b1aa5e907d489619fb43d233c3336bfc03d/lib/child_process.js#L333
240
+ // and it should be a positive integer
241
+ if (lineNumber && !(Number.isInteger(lineNumber) && lineNumber > 0)) {
242
+ return { status: 'error', message: 'lineNumber must be a positive integer' };
243
+ }
244
+ // colNumber is optional, but should be a positive integer too
245
+ // default is 1
246
+ if (colNumber && !(Number.isInteger(colNumber) && colNumber > 0)) {
247
+ colNumber = 1;
248
+ }
249
+ const editorInfo = guessEditor();
250
+ const editor = editorInfo[0];
251
+ let args = editorInfo.slice(1).filter(Boolean);
252
+ if (!editor) {
253
+ return { status: 'error', message: 'No editor found' };
254
+ }
255
+ if (editor.toLowerCase() === 'none') {
256
+ return { status: 'error', message: 'Editor set to "none"' };
257
+ }
258
+ if (typeof pathList === 'string') {
259
+ pathList = [pathList];
260
+ }
261
+ const initArgs = { fileList: [], errorsList: [] };
262
+ const { fileList, errorsList } = pathList.reduce((acc, fileName) => {
263
+ if (process.platform === 'linux' &&
264
+ fileName.startsWith('/mnt/') &&
265
+ /Microsoft/i.test(os.release())) {
266
+ // Assume WSL / "Bash on Ubuntu on Windows" is being used, and
267
+ // that the file exists on the Windows file system.
268
+ // `os.release()` is "4.4.0-43-Microsoft" in the current release
269
+ // build of WSL, see: https://github.com/Microsoft/BashOnWindows/issues/423#issuecomment-221627364
270
+ // When a Windows editor is specified, interop functionality can
271
+ // handle the path translation, but only if a relative path is used.
272
+ fileName = path.relative('', fileName);
273
+ }
274
+ const fileExists = fs.existsSync(fileName);
275
+ // cmd.exe on Windows is vulnerable to RCE attacks given a file name of the
276
+ // form "C:\Users\myusername\Downloads\& curl 172.21.93.52". Use a whitelist
277
+ // to validate user-provided file names. This doesn't cover the entire range
278
+ // of valid file names but should cover almost all of them in practice.
279
+ // if the file exists, then we're good.
280
+ if (!fileExists &&
281
+ process.platform === 'win32' &&
282
+ !WINDOWS_FILE_NAME_WHITELIST.test(fileName)) {
283
+ acc.errorsList.push(fileName);
284
+ }
285
+ else {
286
+ if (!fileExists) {
287
+ fsExtra.ensureDirSync(path.dirname(fileName));
288
+ fsExtra.writeFileSync(fileName, '', 'utf8');
289
+ }
290
+ acc.fileList.push(fileName.trim());
291
+ }
292
+ return acc;
293
+ }, initArgs);
294
+ // TODO: figure out how to send error messages as JSX from here...
295
+ function getErrorMessage() {
296
+ let message;
297
+ if (errorsList.length) {
298
+ const readableName = errorsList.length === 1 ? readablePath(errorsList[0]) : 'some files';
299
+ message = `Could not open ${readableName} in the editor.\n\nWhen running on Windows, file names are checked against a whitelist to protect against remote code execution attacks.\nFile names may consist only of alphanumeric characters (all languages), periods, dashes, slashes, and underscores. Maybe you have your files in a folder that includes a space in the pathname? Rename the folder to remove the space and try again.`;
300
+ }
301
+ else {
302
+ message = 'pathList must contain at least one valid file path';
303
+ }
304
+ return {
305
+ status: 'error',
306
+ message,
307
+ };
308
+ }
309
+ const workspace = null;
310
+ if (lineNumber && fileList.length === 1) {
311
+ const fileName = fileList[0];
312
+ if (!fileName) {
313
+ return getErrorMessage();
314
+ }
315
+ args = args.concat(getArgumentsForLineNumber(editor, fileName, lineNumber, colNumber, workspace)
316
+ .filter(Boolean)
317
+ .map(String));
318
+ }
319
+ else {
320
+ const argList = fileList.filter(Boolean);
321
+ if (!argList.length) {
322
+ return getErrorMessage();
323
+ }
324
+ args.push(...argList);
325
+ }
326
+ if (_childProcess && isTerminalEditor(editor)) {
327
+ // There's an existing editor process already and it's attached
328
+ // to the terminal, so go kill it. Otherwise two separate editor
329
+ // instances attach to the stdin/stdout which gets confusing.
330
+ _childProcess.kill('SIGKILL');
331
+ }
332
+ return new Promise((res) => {
333
+ if (process.platform === 'win32') {
334
+ // On Windows, launch the editor in a shell because spawn can only
335
+ // launch .exe files.
336
+ _childProcess = child_process.spawn('cmd.exe', ['/C', editor].concat(args).filter(Boolean), { stdio: ['inherit', 'inherit', 'pipe'] });
337
+ }
338
+ else {
339
+ _childProcess = child_process.spawn(editor, args, {
340
+ stdio: ['inherit', 'inherit', 'pipe'],
341
+ });
342
+ }
343
+ _childProcess.stderr?.on('data', (data) => {
344
+ const message = String(data);
345
+ // Filter out the specific error message for environment variable issues
346
+ if (!message.includes('Node.js environment variables are disabled')) {
347
+ process.stderr.write(data); // Only write non-filtered messages to stderr
348
+ }
349
+ });
350
+ _childProcess.on('exit', async (errorCode) => {
351
+ _childProcess = null;
352
+ if (errorCode) {
353
+ const readableName = fileList.length === 1 ? readablePath(fileList[0]) : 'some files';
354
+ return res({
355
+ status: 'error',
356
+ message: `Could not open ${readableName} in the editor.\n\nThe editor process exited with an error code (${errorCode}).`,
357
+ });
358
+ }
359
+ else if (errorsList.length) {
360
+ // show error message even when the editor was opened successfully,
361
+ // if some file path was not valid in windows
362
+ return res(getErrorMessage());
363
+ }
364
+ else {
365
+ return res({ status: 'success' });
366
+ }
367
+ });
368
+ _childProcess.on('error', async (error) => {
369
+ if (error.code === 'EBADF') {
370
+ return res({
371
+ status: 'error',
372
+ message: 'Unable to launch editor. This commonly happens when running in a containerized or server environment without terminal access.',
373
+ });
374
+ }
375
+ return res({ status: 'error', message: error.message });
376
+ });
377
+ });
378
+ }
379
+ //# sourceMappingURL=launch-editor.server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"launch-editor.server.js","sourceRoot":"","sources":["../../src/launch-editor.server.ts"],"names":[],"mappings":"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","sourcesContent":["// copied (and barely modified) from create-react-app:\n// https://github.com/facebook/create-react-app/blob/d960b9e38c062584ff6cfb1a70e1512509a966e7/packages/react-dev-utils/launchEditor.js\n\nimport child_process from 'child_process'\nimport fs from 'fs'\nimport os from 'os'\nimport path from 'path'\nimport fsExtra from 'fs-extra'\nimport shellQuote from 'shell-quote'\nimport { getRelativePath } from './apps.server.js'\n\nfunction readablePath(filePath: string = '') {\n\tconst relative = getRelativePath(filePath)\n\tconst name = path.basename(relative)\n\tconst dir = path.dirname(relative)\n\treturn `'${name}' from:\\n'${dir}'`\n}\n\nfunction isTerminalEditor(editor: string) {\n\tswitch (editor) {\n\t\tcase 'vim':\n\t\tcase 'emacs':\n\t\tcase 'nano':\n\t\t\treturn true\n\t}\n\treturn false\n}\n\n// Map from full process name to binary that starts the process\n// We can't just re-use full process name, because it will spawn a new instance\n// of the app every time\nconst COMMON_EDITORS_OSX = {\n\t'/Applications/Atom.app/Contents/MacOS/Atom': 'atom',\n\t'/Applications/Atom Beta.app/Contents/MacOS/Atom Beta':\n\t\t'/Applications/Atom Beta.app/Contents/MacOS/Atom Beta',\n\t'/Applications/Brackets.app/Contents/MacOS/Brackets': 'brackets',\n\t'/Applications/Sublime Text.app/Contents/MacOS/Sublime Text':\n\t\t'/Applications/Sublime Text.app/Contents/SharedSupport/bin/subl',\n\t'/Applications/Sublime Text Dev.app/Contents/MacOS/Sublime Text':\n\t\t'/Applications/Sublime Text Dev.app/Contents/SharedSupport/bin/subl',\n\t'/Applications/Sublime Text 2.app/Contents/MacOS/Sublime Text 2':\n\t\t'/Applications/Sublime Text 2.app/Contents/SharedSupport/bin/subl',\n\t'/Applications/Cursor.app/Contents/MacOS/Cursor': 'cursor',\n\t'/Applications/Visual Studio Code.app/Contents/MacOS/Electron': 'code',\n\t'/Applications/Visual Studio Code - Insiders.app/Contents/MacOS/Electron':\n\t\t'code-insiders',\n\t'/Applications/VSCodium.app/Contents/MacOS/Electron': 'vscodium',\n\t'/Applications/AppCode.app/Contents/MacOS/appcode':\n\t\t'/Applications/AppCode.app/Contents/MacOS/appcode',\n\t'/Applications/CLion.app/Contents/MacOS/clion':\n\t\t'/Applications/CLion.app/Contents/MacOS/clion',\n\t'/Applications/IntelliJ IDEA.app/Contents/MacOS/idea':\n\t\t'/Applications/IntelliJ IDEA.app/Contents/MacOS/idea',\n\t'/Applications/PhpStorm.app/Contents/MacOS/phpstorm':\n\t\t'/Applications/PhpStorm.app/Contents/MacOS/phpstorm',\n\t'/Applications/PyCharm.app/Contents/MacOS/pycharm':\n\t\t'/Applications/PyCharm.app/Contents/MacOS/pycharm',\n\t'/Applications/PyCharm CE.app/Contents/MacOS/pycharm':\n\t\t'/Applications/PyCharm CE.app/Contents/MacOS/pycharm',\n\t'/Applications/RubyMine.app/Contents/MacOS/rubymine':\n\t\t'/Applications/RubyMine.app/Contents/MacOS/rubymine',\n\t'/Applications/WebStorm.app/Contents/MacOS/webstorm':\n\t\t'/Applications/WebStorm.app/Contents/MacOS/webstorm',\n\t'/Applications/MacVim.app/Contents/MacOS/MacVim': 'mvim',\n\t'/Applications/GoLand.app/Contents/MacOS/goland':\n\t\t'/Applications/GoLand.app/Contents/MacOS/goland',\n\t'/Applications/Rider.app/Contents/MacOS/rider':\n\t\t'/Applications/Rider.app/Contents/MacOS/rider',\n\t'/Applications/Zed/Zed.app/Contents/MacOS/zed': 'zed',\n} as const\n\nconst COMMON_EDITORS_LINUX = {\n\tatom: 'atom',\n\tBrackets: 'brackets',\n\tcursor: 'cursor',\n\tcode: 'code',\n\t'code-insiders': 'code-insiders',\n\tvscodium: 'vscodium',\n\temacs: 'emacs',\n\tgvim: 'gvim',\n\t'idea.sh': 'idea',\n\t'phpstorm.sh': 'phpstorm',\n\t'pycharm.sh': 'pycharm',\n\t'rubymine.sh': 'rubymine',\n\tsublime_text: 'sublime_text',\n\tvim: 'vim',\n\t'webstorm.sh': 'webstorm',\n\t'goland.sh': 'goland',\n\t'rider.sh': 'rider',\n\tzed: 'zed',\n}\n\nconst COMMON_EDITORS_WIN = [\n\t'Brackets.exe',\n\t'Cursor.exe',\n\t'Code.exe',\n\t'Code - Insiders.exe',\n\t'VSCodium.exe',\n\t'atom.exe',\n\t'sublime_text.exe',\n\t'notepad++.exe',\n\t'clion.exe',\n\t'clion64.exe',\n\t'idea.exe',\n\t'idea64.exe',\n\t'phpstorm.exe',\n\t'phpstorm64.exe',\n\t'pycharm.exe',\n\t'pycharm64.exe',\n\t'rubymine.exe',\n\t'rubymine64.exe',\n\t'webstorm.exe',\n\t'webstorm64.exe',\n\t'goland.exe',\n\t'goland64.exe',\n\t'rider.exe',\n\t'rider64.exe',\n\t'zed.exe',\n]\n\n// Transpiled version of: /^([A-Za-z]:[/\\\\])?[\\p{L}0-9/.\\-_\\\\]+$/u\n// Non-transpiled version requires support for Unicode property regex. Allows\n// alphanumeric characters, periods, dashes, slashes, and underscores.\nconst WINDOWS_FILE_NAME_WHITELIST =\n\t/^([A-Za-z]:[/\\\\])?(?:[\\x2D-9A-Z\\\\_a-z\\xAA\\xB5\\xBA\\xC0-\\xD6\\xD8-\\xF6\\xF8-\\u02C1\\u02C6-\\u02D1\\u02E0-\\u02E4\\u02EC\\u02EE\\u0370-\\u0374\\u0376\\u0377\\u037A-\\u037D\\u037F\\u0386\\u0388-\\u038A\\u038C\\u038E-\\u03A1\\u03A3-\\u03F5\\u03F7-\\u0481\\u048A-\\u052F\\u0531-\\u0556\\u0559\\u0560-\\u0588\\u05D0-\\u05EA\\u05EF-\\u05F2\\u0620-\\u064A\\u066E\\u066F\\u0671-\\u06D3\\u06D5\\u06E5\\u06E6\\u06EE\\u06EF\\u06FA-\\u06FC\\u06FF\\u0710\\u0712-\\u072F\\u074D-\\u07A5\\u07B1\\u07CA-\\u07EA\\u07F4\\u07F5\\u07FA\\u0800-\\u0815\\u081A\\u0824\\u0828\\u0840-\\u0858\\u0860-\\u086A\\u08A0-\\u08B4\\u08B6-\\u08BD\\u0904-\\u0939\\u093D\\u0950\\u0958-\\u0961\\u0971-\\u0980\\u0985-\\u098C\\u098F\\u0990\\u0993-\\u09A8\\u09AA-\\u09B0\\u09B2\\u09B6-\\u09B9\\u09BD\\u09CE\\u09DC\\u09DD\\u09DF-\\u09E1\\u09F0\\u09F1\\u09FC\\u0A05-\\u0A0A\\u0A0F\\u0A10\\u0A13-\\u0A28\\u0A2A-\\u0A30\\u0A32\\u0A33\\u0A35\\u0A36\\u0A38\\u0A39\\u0A59-\\u0A5C\\u0A5E\\u0A72-\\u0A74\\u0A85-\\u0A8D\\u0A8F-\\u0A91\\u0A93-\\u0AA8\\u0AAA-\\u0AB0\\u0AB2\\u0AB3\\u0AB5-\\u0AB9\\u0ABD\\u0AD0\\u0AE0\\u0AE1\\u0AF9\\u0B05-\\u0B0C\\u0B0F\\u0B10\\u0B13-\\u0B28\\u0B2A-\\u0B30\\u0B32\\u0B33\\u0B35-\\u0B39\\u0B3D\\u0B5C\\u0B5D\\u0B5F-\\u0B61\\u0B71\\u0B83\\u0B85-\\u0B8A\\u0B8E-\\u0B90\\u0B92-\\u0B95\\u0B99\\u0B9A\\u0B9C\\u0B9E\\u0B9F\\u0BA3\\u0BA4\\u0BA8-\\u0BAA\\u0BAE-\\u0BB9\\u0BD0\\u0C05-\\u0C0C\\u0C0E-\\u0C10\\u0C12-\\u0C28\\u0C2A-\\u0C39\\u0C3D\\u0C58-\\u0C5A\\u0C60\\u0C61\\u0C80\\u0C85-\\u0C8C\\u0C8E-\\u0C90\\u0C92-\\u0CA8\\u0CAA-\\u0CB3\\u0CB5-\\u0CB9\\u0CBD\\u0CDE\\u0CE0\\u0CE1\\u0CF1\\u0CF2\\u0D05-\\u0D0C\\u0D0E-\\u0D10\\u0D12-\\u0D3A\\u0D3D\\u0D4E\\u0D54-\\u0D56\\u0D5F-\\u0D61\\u0D7A-\\u0D7F\\u0D85-\\u0D96\\u0D9A-\\u0DB1\\u0DB3-\\u0DBB\\u0DBD\\u0DC0-\\u0DC6\\u0E01-\\u0E30\\u0E32\\u0E33\\u0E40-\\u0E46\\u0E81\\u0E82\\u0E84\\u0E87\\u0E88\\u0E8A\\u0E8D\\u0E94-\\u0E97\\u0E99-\\u0E9F\\u0EA1-\\u0EA3\\u0EA5\\u0EA7\\u0EAA\\u0EAB\\u0EAD-\\u0EB0\\u0EB2\\u0EB3\\u0EBD\\u0EC0-\\u0EC4\\u0EC6\\u0EDC-\\u0EDF\\u0F00\\u0F40-\\u0F47\\u0F49-\\u0F6C\\u0F88-\\u0F8C\\u1000-\\u102A\\u103F\\u1050-\\u1055\\u105A-\\u105D\\u1061\\u1065\\u1066\\u106E-\\u1070\\u1075-\\u1081\\u108E\\u10A0-\\u10C5\\u10C7\\u10CD\\u10D0-\\u10FA\\u10FC-\\u1248\\u124A-\\u124D\\u1250-\\u1256\\u1258\\u125A-\\u125D\\u1260-\\u1288\\u128A-\\u128D\\u1290-\\u12B0\\u12B2-\\u12B5\\u12B8-\\u12BE\\u12C0\\u12C2-\\u12C5\\u12C8-\\u12D6\\u12D8-\\u1310\\u1312-\\u1315\\u1318-\\u135A\\u1380-\\u138F\\u13A0-\\u13F5\\u13F8-\\u13FD\\u1401-\\u166C\\u166F-\\u167F\\u1681-\\u169A\\u16A0-\\u16EA\\u16F1-\\u16F8\\u1700-\\u170C\\u170E-\\u1711\\u1720-\\u1731\\u1740-\\u1751\\u1760-\\u176C\\u176E-\\u1770\\u1780-\\u17B3\\u17D7\\u17DC\\u1820-\\u1878\\u1880-\\u1884\\u1887-\\u18A8\\u18AA\\u18B0-\\u18F5\\u1900-\\u191E\\u1950-\\u196D\\u1970-\\u1974\\u1980-\\u19AB\\u19B0-\\u19C9\\u1A00-\\u1A16\\u1A20-\\u1A54\\u1AA7\\u1B05-\\u1B33\\u1B45-\\u1B4B\\u1B83-\\u1BA0\\u1BAE\\u1BAF\\u1BBA-\\u1BE5\\u1C00-\\u1C23\\u1C4D-\\u1C4F\\u1C5A-\\u1C7D\\u1C80-\\u1C88\\u1C90-\\u1CBA\\u1CBD-\\u1CBF\\u1CE9-\\u1CEC\\u1CEE-\\u1CF1\\u1CF5\\u1CF6\\u1D00-\\u1DBF\\u1E00-\\u1F15\\u1F18-\\u1F1D\\u1F20-\\u1F45\\u1F48-\\u1F4D\\u1F50-\\u1F57\\u1F59\\u1F5B\\u1F5D\\u1F5F-\\u1F7D\\u1F80-\\u1FB4\\u1FB6-\\u1FBC\\u1FBE\\u1FC2-\\u1FC4\\u1FC6-\\u1FCC\\u1FD0-\\u1FD3\\u1FD6-\\u1FDB\\u1FE0-\\u1FEC\\u1FF2-\\u1FF4\\u1FF6-\\u1FFC\\u2071\\u207F\\u2090-\\u209C\\u2102\\u2107\\u210A-\\u2113\\u2115\\u2119-\\u211D\\u2124\\u2126\\u2128\\u212A-\\u212D\\u212F-\\u2139\\u213C-\\u213F\\u2145-\\u2149\\u214E\\u2183\\u2184\\u2C00-\\u2C2E\\u2C30-\\u2C5E\\u2C60-\\u2CE4\\u2CEB-\\u2CEE\\u2CF2\\u2CF3\\u2D00-\\u2D25\\u2D27\\u2D2D\\u2D30-\\u2D67\\u2D6F\\u2D80-\\u2D96\\u2DA0-\\u2DA6\\u2DA8-\\u2DAE\\u2DB0-\\u2DB6\\u2DB8-\\u2DBE\\u2DC0-\\u2DC6\\u2DC8-\\u2DCE\\u2DD0-\\u2DD6\\u2DD8-\\u2DDE\\u2E2F\\u3005\\u3006\\u3031-\\u3035\\u303B\\u303C\\u3041-\\u3096\\u309D-\\u309F\\u30A1-\\u30FA\\u30FC-\\u30FF\\u3105-\\u312F\\u3131-\\u318E\\u31A0-\\u31BA\\u31F0-\\u31FF\\u3400-\\u4DB5\\u4E00-\\u9FEF\\uA000-\\uA48C\\uA4D0-\\uA4FD\\uA500-\\uA60C\\uA610-\\uA61F\\uA62A\\uA62B\\uA640-\\uA66E\\uA67F-\\uA69D\\uA6A0-\\uA6E5\\uA717-\\uA71F\\uA722-\\uA788\\uA78B-\\uA7B9\\uA7F7-\\uA801\\uA803-\\uA805\\uA807-\\uA80A\\uA80C-\\uA822\\uA840-\\uA873\\uA882-\\uA8B3\\uA8F2-\\uA8F7\\uA8FB\\uA8FD\\uA8FE\\uA90A-\\uA925\\uA930-\\uA946\\uA960-\\uA97C\\uA984-\\uA9B2\\uA9CF\\uA9E0-\\uA9E4\\uA9E6-\\uA9EF\\uA9FA-\\uA9FE\\uAA00-\\uAA28\\uAA40-\\uAA42\\uAA44-\\uAA4B\\uAA60-\\uAA76\\uAA7A\\uAA7E-\\uAAAF\\uAAB1\\uAAB5\\uAAB6\\uAAB9-\\uAABD\\uAAC0\\uAAC2\\uAADB-\\uAADD\\uAAE0-\\uAAEA\\uAAF2-\\uAAF4\\uAB01-\\uAB06\\uAB09-\\uAB0E\\uAB11-\\uAB16\\uAB20-\\uAB26\\uAB28-\\uAB2E\\uAB30-\\uAB5A\\uAB5C-\\uAB65\\uAB70-\\uABE2\\uAC00-\\uD7A3\\uD7B0-\\uD7C6\\uD7CB-\\uD7FB\\uF900-\\uFA6D\\uFA70-\\uFAD9\\uFB00-\\uFB06\\uFB13-\\uFB17\\uFB1D\\uFB1F-\\uFB28\\uFB2A-\\uFB36\\uFB38-\\uFB3C\\uFB3E\\uFB40\\uFB41\\uFB43\\uFB44\\uFB46-\\uFBB1\\uFBD3-\\uFD3D\\uFD50-\\uFD8F\\uFD92-\\uFDC7\\uFDF0-\\uFDFB\\uFE70-\\uFE74\\uFE76-\\uFEFC\\uFF21-\\uFF3A\\uFF41-\\uFF5A\\uFF66-\\uFFBE\\uFFC2-\\uFFC7\\uFFCA-\\uFFCF\\uFFD2-\\uFFD7\\uFFDA-\\uFFDC]|\\uD800[\\uDC00-\\uDC0B\\uDC0D-\\uDC26\\uDC28-\\uDC3A\\uDC3C\\uDC3D\\uDC3F-\\uDC4D\\uDC50-\\uDC5D\\uDC80-\\uDCFA\\uDE80-\\uDE9C\\uDEA0-\\uDED0\\uDF00-\\uDF1F\\uDF2D-\\uDF40\\uDF42-\\uDF49\\uDF50-\\uDF75\\uDF80-\\uDF9D\\uDFA0-\\uDFC3\\uDFC8-\\uDFCF]|\\uD801[\\uDC00-\\uDC9D\\uDCB0-\\uDCD3\\uDCD8-\\uDCFB\\uDD00-\\uDD27\\uDD30-\\uDD63\\uDE00-\\uDF36\\uDF40-\\uDF55\\uDF60-\\uDF67]|\\uD802[\\uDC00-\\uDC05\\uDC08\\uDC0A-\\uDC35\\uDC37\\uDC38\\uDC3C\\uDC3F-\\uDC55\\uDC60-\\uDC76\\uDC80-\\uDC9E\\uDCE0-\\uDCF2\\uDCF4\\uDCF5\\uDD00-\\uDD15\\uDD20-\\uDD39\\uDD80-\\uDDB7\\uDDBE\\uDDBF\\uDE00\\uDE10-\\uDE13\\uDE15-\\uDE17\\uDE19-\\uDE35\\uDE60-\\uDE7C\\uDE80-\\uDE9C\\uDEC0-\\uDEC7\\uDEC9-\\uDEE4\\uDF00-\\uDF35\\uDF40-\\uDF55\\uDF60-\\uDF72\\uDF80-\\uDF91]|\\uD803[\\uDC00-\\uDC48\\uDC80-\\uDCB2\\uDCC0-\\uDCF2\\uDD00-\\uDD23\\uDF00-\\uDF1C\\uDF27\\uDF30-\\uDF45]|\\uD804[\\uDC03-\\uDC37\\uDC83-\\uDCAF\\uDCD0-\\uDCE8\\uDD03-\\uDD26\\uDD44\\uDD50-\\uDD72\\uDD76\\uDD83-\\uDDB2\\uDDC1-\\uDDC4\\uDDDA\\uDDDC\\uDE00-\\uDE11\\uDE13-\\uDE2B\\uDE80-\\uDE86\\uDE88\\uDE8A-\\uDE8D\\uDE8F-\\uDE9D\\uDE9F-\\uDEA8\\uDEB0-\\uDEDE\\uDF05-\\uDF0C\\uDF0F\\uDF10\\uDF13-\\uDF28\\uDF2A-\\uDF30\\uDF32\\uDF33\\uDF35-\\uDF39\\uDF3D\\uDF50\\uDF5D-\\uDF61]|\\uD805[\\uDC00-\\uDC34\\uDC47-\\uDC4A\\uDC80-\\uDCAF\\uDCC4\\uDCC5\\uDCC7\\uDD80-\\uDDAE\\uDDD8-\\uDDDB\\uDE00-\\uDE2F\\uDE44\\uDE80-\\uDEAA\\uDF00-\\uDF1A]|\\uD806[\\uDC00-\\uDC2B\\uDCA0-\\uDCDF\\uDCFF\\uDE00\\uDE0B-\\uDE32\\uDE3A\\uDE50\\uDE5C-\\uDE83\\uDE86-\\uDE89\\uDE9D\\uDEC0-\\uDEF8]|\\uD807[\\uDC00-\\uDC08\\uDC0A-\\uDC2E\\uDC40\\uDC72-\\uDC8F\\uDD00-\\uDD06\\uDD08\\uDD09\\uDD0B-\\uDD30\\uDD46\\uDD60-\\uDD65\\uDD67\\uDD68\\uDD6A-\\uDD89\\uDD98\\uDEE0-\\uDEF2]|\\uD808[\\uDC00-\\uDF99]|\\uD809[\\uDC80-\\uDD43]|[\\uD80C\\uD81C-\\uD820\\uD840-\\uD868\\uD86A-\\uD86C\\uD86F-\\uD872\\uD874-\\uD879][\\uDC00-\\uDFFF]|\\uD80D[\\uDC00-\\uDC2E]|\\uD811[\\uDC00-\\uDE46]|\\uD81A[\\uDC00-\\uDE38\\uDE40-\\uDE5E\\uDED0-\\uDEED\\uDF00-\\uDF2F\\uDF40-\\uDF43\\uDF63-\\uDF77\\uDF7D-\\uDF8F]|\\uD81B[\\uDE40-\\uDE7F\\uDF00-\\uDF44\\uDF50\\uDF93-\\uDF9F\\uDFE0\\uDFE1]|\\uD821[\\uDC00-\\uDFF1]|\\uD822[\\uDC00-\\uDEF2]|\\uD82C[\\uDC00-\\uDD1E\\uDD70-\\uDEFB]|\\uD82F[\\uDC00-\\uDC6A\\uDC70-\\uDC7C\\uDC80-\\uDC88\\uDC90-\\uDC99]|\\uD835[\\uDC00-\\uDC54\\uDC56-\\uDC9C\\uDC9E\\uDC9F\\uDCA2\\uDCA5\\uDCA6\\uDCA9-\\uDCAC\\uDCAE-\\uDCB9\\uDCBB\\uDCBD-\\uDCC3\\uDCC5-\\uDD05\\uDD07-\\uDD0A\\uDD0D-\\uDD14\\uDD16-\\uDD1C\\uDD1E-\\uDD39\\uDD3B-\\uDD3E\\uDD40-\\uDD44\\uDD46\\uDD4A-\\uDD50\\uDD52-\\uDEA5\\uDEA8-\\uDEC0\\uDEC2-\\uDEDA\\uDEDC-\\uDEFA\\uDEFC-\\uDF14\\uDF16-\\uDF34\\uDF36-\\uDF4E\\uDF50-\\uDF6E\\uDF70-\\uDF88\\uDF8A-\\uDFA8\\uDFAA-\\uDFC2\\uDFC4-\\uDFCB]|\\uD83A[\\uDC00-\\uDCC4\\uDD00-\\uDD43]|\\uD83B[\\uDE00-\\uDE03\\uDE05-\\uDE1F\\uDE21\\uDE22\\uDE24\\uDE27\\uDE29-\\uDE32\\uDE34-\\uDE37\\uDE39\\uDE3B\\uDE42\\uDE47\\uDE49\\uDE4B\\uDE4D-\\uDE4F\\uDE51\\uDE52\\uDE54\\uDE57\\uDE59\\uDE5B\\uDE5D\\uDE5F\\uDE61\\uDE62\\uDE64\\uDE67-\\uDE6A\\uDE6C-\\uDE72\\uDE74-\\uDE77\\uDE79-\\uDE7C\\uDE7E\\uDE80-\\uDE89\\uDE8B-\\uDE9B\\uDEA1-\\uDEA3\\uDEA5-\\uDEA9\\uDEAB-\\uDEBB]|\\uD869[\\uDC00-\\uDED6\\uDF00-\\uDFFF]|\\uD86D[\\uDC00-\\uDF34\\uDF40-\\uDFFF]|\\uD86E[\\uDC00-\\uDC1D\\uDC20-\\uDFFF]|\\uD873[\\uDC00-\\uDEA1\\uDEB0-\\uDFFF]|\\uD87A[\\uDC00-\\uDFE0]|\\uD87E[\\uDC00-\\uDE1D])+$/\n\nfunction addWorkspaceToArgumentsIfExists(\n\targs: Array<string>,\n\tworkspace: string | null,\n) {\n\tif (workspace) {\n\t\targs.unshift(workspace)\n\t}\n\treturn args\n}\n\nfunction getArgumentsForLineNumber(\n\teditor: string,\n\tfileName: string,\n\tlineNumber: number,\n\tcolNumber: number | undefined,\n\tworkspace: string | null,\n) {\n\tconst editorBasename = path.basename(editor).replace(/\\.(exe|cmd|bat)$/i, '')\n\tswitch (editorBasename) {\n\t\tcase 'atom':\n\t\tcase 'Atom':\n\t\tcase 'Atom Beta':\n\t\tcase 'subl':\n\t\tcase 'sublime':\n\t\tcase 'sublime_text':\n\t\t\treturn [`${fileName}:${lineNumber}:${colNumber}`]\n\t\tcase 'wstorm':\n\t\tcase 'charm':\n\t\t\treturn [`${fileName}:${lineNumber}`]\n\t\tcase 'notepad++':\n\t\t\treturn [`-n${lineNumber}`, `-c${colNumber}`, fileName]\n\t\tcase 'vim':\n\t\tcase 'mvim':\n\t\tcase 'joe':\n\t\tcase 'gvim':\n\t\t\treturn [`+${lineNumber}`, fileName]\n\t\tcase 'emacs':\n\t\tcase 'emacsclient':\n\t\t\treturn [`+${lineNumber}:${colNumber}`, fileName]\n\t\tcase 'rmate':\n\t\tcase 'mate':\n\t\tcase 'mine':\n\t\t\treturn ['--line', lineNumber, fileName]\n\t\tcase 'cursor':\n\t\tcase 'code':\n\t\tcase 'Code':\n\t\tcase 'code-insiders':\n\t\tcase 'Code - Insiders':\n\t\tcase 'vscodium':\n\t\tcase 'VSCodium':\n\t\t\treturn addWorkspaceToArgumentsIfExists(\n\t\t\t\t['-g', `${fileName}:${lineNumber}:${colNumber}`],\n\t\t\t\tworkspace,\n\t\t\t)\n\t\tcase 'appcode':\n\t\tcase 'clion':\n\t\tcase 'clion64':\n\t\tcase 'idea':\n\t\tcase 'idea64':\n\t\tcase 'phpstorm':\n\t\tcase 'phpstorm64':\n\t\tcase 'pycharm':\n\t\tcase 'pycharm64':\n\t\tcase 'rubymine':\n\t\tcase 'rubymine64':\n\t\tcase 'webstorm':\n\t\tcase 'webstorm64':\n\t\tcase 'goland':\n\t\tcase 'goland64':\n\t\tcase 'rider':\n\t\tcase 'rider64':\n\t\t\treturn addWorkspaceToArgumentsIfExists(\n\t\t\t\t['--line', lineNumber.toString(), fileName],\n\t\t\t\tworkspace,\n\t\t\t)\n\t}\n\n\t// For all others, drop the lineNumber until we have\n\t// a mapping above, since providing the lineNumber incorrectly\n\t// can result in errors or confusing behavior.\n\treturn [fileName]\n}\n\nfunction guessEditor(): Array<string | null> {\n\t// Explicit config always wins\n\tif (process.env.EPICSHOP_EDITOR) {\n\t\treturn shellQuote.parse(process.env.EPICSHOP_EDITOR).map((a) => String(a))\n\t}\n\n\t// We can find out which editor is currently running by:\n\t// `ps x` on macOS and Linux\n\t// `Get-Process` on Windows\n\ttry {\n\t\tif (process.platform === 'darwin') {\n\t\t\tconst output = child_process.execSync('ps x').toString()\n\t\t\tconst processNames = Object.keys(COMMON_EDITORS_OSX) as Array<\n\t\t\t\tkeyof typeof COMMON_EDITORS_OSX\n\t\t\t>\n\t\t\tfor (let i = 0; i < processNames.length; i++) {\n\t\t\t\tconst processName = processNames[i]\n\t\t\t\tif (processName && output.includes(processName)) {\n\t\t\t\t\tconst editor = COMMON_EDITORS_OSX[processName]\n\t\t\t\t\treturn [editor]\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (process.platform === 'win32') {\n\t\t\t// Some processes need elevated rights to get its executable path.\n\t\t\t// Just filter them out upfront. This also saves 10-20ms on the command.\n\t\t\tconst output = child_process\n\t\t\t\t.execSync(\n\t\t\t\t\t'wmic process where \"executablepath is not null\" get executablepath',\n\t\t\t\t)\n\t\t\t\t.toString()\n\t\t\tconst runningProcesses = output.split('\\r\\n')\n\t\t\tfor (let i = 0; i < runningProcesses.length; i++) {\n\t\t\t\tconst processPath = runningProcesses[i]?.trim()\n\t\t\t\tif (!processPath) continue\n\t\t\t\tconst processName = path.basename(processPath)\n\t\t\t\tif (COMMON_EDITORS_WIN.includes(processName)) {\n\t\t\t\t\treturn [processPath]\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (process.platform === 'linux') {\n\t\t\t// --no-heading No header line\n\t\t\t// x List all processes owned by you\n\t\t\t// -o comm Need only names column\n\t\t\tconst output = child_process\n\t\t\t\t.execSync('ps x --no-heading -o comm --sort=comm')\n\t\t\t\t.toString()\n\t\t\tconst processNames = Object.keys(COMMON_EDITORS_LINUX)\n\t\t\tfor (let i = 0; i < processNames.length; i++) {\n\t\t\t\tconst processName = processNames[i]\n\t\t\t\tif (!processName) continue\n\t\t\t\tif (output.includes(processName)) {\n\t\t\t\t\t// @ts-expect-error 🤷‍♂️ it's fine\n\t\t\t\t\treturn [COMMON_EDITORS_LINUX[processName]]\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} catch {\n\t\t// Ignore...\n\t}\n\n\t// Last resort, use old skool env vars\n\tif (process.env.VISUAL) {\n\t\treturn [process.env.VISUAL]\n\t} else if (process.env.EDITOR) {\n\t\treturn [process.env.EDITOR]\n\t}\n\n\treturn [null]\n}\n\nlet _childProcess: ReturnType<typeof child_process.spawn> | null = null\nexport type Result =\n\t| { status: 'success' }\n\t| { status: 'error'; message: string }\nexport async function launchEditor(\n\tpathList: string[] | string,\n\tlineNumber: number = 1,\n\tcolNumber: number = 1,\n): Promise<Result> {\n\t// Sanitize lineNumber to prevent malicious use on win32\n\t// via: https://github.com/nodejs/node/blob/c3bb4b1aa5e907d489619fb43d233c3336bfc03d/lib/child_process.js#L333\n\t// and it should be a positive integer\n\tif (lineNumber && !(Number.isInteger(lineNumber) && lineNumber > 0)) {\n\t\treturn { status: 'error', message: 'lineNumber must be a positive integer' }\n\t}\n\n\t// colNumber is optional, but should be a positive integer too\n\t// default is 1\n\tif (colNumber && !(Number.isInteger(colNumber) && colNumber > 0)) {\n\t\tcolNumber = 1\n\t}\n\n\tconst editorInfo = guessEditor()\n\tconst editor = editorInfo[0]\n\tlet args = editorInfo.slice(1).filter(Boolean)\n\n\tif (!editor) {\n\t\treturn { status: 'error', message: 'No editor found' }\n\t}\n\n\tif (editor.toLowerCase() === 'none') {\n\t\treturn { status: 'error', message: 'Editor set to \"none\"' }\n\t}\n\n\tif (typeof pathList === 'string') {\n\t\tpathList = [pathList]\n\t}\n\n\ttype accumulator = {\n\t\tfileList: string[]\n\t\terrorsList: string[]\n\t}\n\n\tconst initArgs: accumulator = { fileList: [], errorsList: [] }\n\n\tconst { fileList, errorsList } = pathList.reduce(\n\t\t(acc: accumulator, fileName: string) => {\n\t\t\tif (\n\t\t\t\tprocess.platform === 'linux' &&\n\t\t\t\tfileName.startsWith('/mnt/') &&\n\t\t\t\t/Microsoft/i.test(os.release())\n\t\t\t) {\n\t\t\t\t// Assume WSL / \"Bash on Ubuntu on Windows\" is being used, and\n\t\t\t\t// that the file exists on the Windows file system.\n\t\t\t\t// `os.release()` is \"4.4.0-43-Microsoft\" in the current release\n\t\t\t\t// build of WSL, see: https://github.com/Microsoft/BashOnWindows/issues/423#issuecomment-221627364\n\t\t\t\t// When a Windows editor is specified, interop functionality can\n\t\t\t\t// handle the path translation, but only if a relative path is used.\n\t\t\t\tfileName = path.relative('', fileName)\n\t\t\t}\n\n\t\t\tconst fileExists = fs.existsSync(fileName)\n\t\t\t// cmd.exe on Windows is vulnerable to RCE attacks given a file name of the\n\t\t\t// form \"C:\\Users\\myusername\\Downloads\\& curl 172.21.93.52\". Use a whitelist\n\t\t\t// to validate user-provided file names. This doesn't cover the entire range\n\t\t\t// of valid file names but should cover almost all of them in practice.\n\t\t\t// if the file exists, then we're good.\n\t\t\tif (\n\t\t\t\t!fileExists &&\n\t\t\t\tprocess.platform === 'win32' &&\n\t\t\t\t!WINDOWS_FILE_NAME_WHITELIST.test(fileName)\n\t\t\t) {\n\t\t\t\tacc.errorsList.push(fileName)\n\t\t\t} else {\n\t\t\t\tif (!fileExists) {\n\t\t\t\t\tfsExtra.ensureDirSync(path.dirname(fileName))\n\t\t\t\t\tfsExtra.writeFileSync(fileName, '', 'utf8')\n\t\t\t\t}\n\n\t\t\t\tacc.fileList.push(fileName.trim())\n\t\t\t}\n\t\t\treturn acc\n\t\t},\n\t\tinitArgs,\n\t)\n\n\t// TODO: figure out how to send error messages as JSX from here...\n\tfunction getErrorMessage() {\n\t\tlet message: string\n\t\tif (errorsList.length) {\n\t\t\tconst readableName =\n\t\t\t\terrorsList.length === 1 ? readablePath(errorsList[0]) : 'some files'\n\t\t\tmessage = `Could not open ${readableName} in the editor.\\n\\nWhen running on Windows, file names are checked against a whitelist to protect against remote code execution attacks.\\nFile names may consist only of alphanumeric characters (all languages), periods, dashes, slashes, and underscores. Maybe you have your files in a folder that includes a space in the pathname? Rename the folder to remove the space and try again.`\n\t\t} else {\n\t\t\tmessage = 'pathList must contain at least one valid file path'\n\t\t}\n\t\treturn {\n\t\t\tstatus: 'error',\n\t\t\tmessage,\n\t\t} as Result\n\t}\n\n\tconst workspace = null\n\tif (lineNumber && fileList.length === 1) {\n\t\tconst fileName = fileList[0]\n\t\tif (!fileName) {\n\t\t\treturn getErrorMessage()\n\t\t}\n\t\targs = args.concat(\n\t\t\tgetArgumentsForLineNumber(\n\t\t\t\teditor,\n\t\t\t\tfileName,\n\t\t\t\tlineNumber,\n\t\t\t\tcolNumber,\n\t\t\t\tworkspace,\n\t\t\t)\n\t\t\t\t.filter(Boolean)\n\t\t\t\t.map(String),\n\t\t)\n\t} else {\n\t\tconst argList = fileList.filter(Boolean)\n\t\tif (!argList.length) {\n\t\t\treturn getErrorMessage()\n\t\t}\n\t\targs.push(...argList)\n\t}\n\n\tif (_childProcess && isTerminalEditor(editor)) {\n\t\t// There's an existing editor process already and it's attached\n\t\t// to the terminal, so go kill it. Otherwise two separate editor\n\t\t// instances attach to the stdin/stdout which gets confusing.\n\t\t_childProcess.kill('SIGKILL')\n\t}\n\n\treturn new Promise((res) => {\n\t\tif (process.platform === 'win32') {\n\t\t\t// On Windows, launch the editor in a shell because spawn can only\n\t\t\t// launch .exe files.\n\t\t\t_childProcess = child_process.spawn(\n\t\t\t\t'cmd.exe',\n\t\t\t\t['/C', editor].concat(args).filter(Boolean),\n\t\t\t\t{ stdio: ['inherit', 'inherit', 'pipe'] },\n\t\t\t)\n\t\t} else {\n\t\t\t_childProcess = child_process.spawn(editor, args, {\n\t\t\t\tstdio: ['inherit', 'inherit', 'pipe'],\n\t\t\t})\n\t\t}\n\t\t_childProcess.stderr?.on('data', (data: string | Uint8Array) => {\n\t\t\tconst message = String(data)\n\t\t\t// Filter out the specific error message for environment variable issues\n\t\t\tif (!message.includes('Node.js environment variables are disabled')) {\n\t\t\t\tprocess.stderr.write(data) // Only write non-filtered messages to stderr\n\t\t\t}\n\t\t})\n\t\t_childProcess.on('exit', async (errorCode) => {\n\t\t\t_childProcess = null\n\n\t\t\tif (errorCode) {\n\t\t\t\tconst readableName =\n\t\t\t\t\tfileList.length === 1 ? readablePath(fileList[0]) : 'some files'\n\t\t\t\treturn res({\n\t\t\t\t\tstatus: 'error',\n\t\t\t\t\tmessage: `Could not open ${readableName} in the editor.\\n\\nThe editor process exited with an error code (${errorCode}).`,\n\t\t\t\t})\n\t\t\t} else if (errorsList.length) {\n\t\t\t\t// show error message even when the editor was opened successfully,\n\t\t\t\t// if some file path was not valid in windows\n\t\t\t\treturn res(getErrorMessage())\n\t\t\t} else {\n\t\t\t\treturn res({ status: 'success' })\n\t\t\t}\n\t\t})\n\n\t\t_childProcess.on('error', async (error: Error & { code?: string }) => {\n\t\t\tif (error.code === 'EBADF') {\n\t\t\t\treturn res({\n\t\t\t\t\tstatus: 'error',\n\t\t\t\t\tmessage:\n\t\t\t\t\t\t'Unable to launch editor. This commonly happens when running in a containerized or server environment without terminal access.',\n\t\t\t\t})\n\t\t\t}\n\t\t\treturn res({ status: 'error', message: error.message })\n\t\t})\n\t})\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@epic-web/workshop-utils",
3
- "version": "6.38.0",
3
+ "version": "6.40.0",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -21,6 +21,7 @@
21
21
  "./config.server": "./src/config.server.ts",
22
22
  "./db.server": "./src/db.server.ts",
23
23
  "./data-storage.server": "./src/data-storage.server.ts",
24
+ "./launch-editor.server": "./src/launch-editor.server.ts",
24
25
  "./timing.server": "./src/timing.server.ts",
25
26
  "./modified-time.server": "./src/modified-time.server.ts",
26
27
  "./compile-mdx.server": "./src/compile-mdx.server.ts",
@@ -93,6 +94,12 @@
93
94
  "default": "./dist/esm/data-storage.server.js"
94
95
  }
95
96
  },
97
+ "./launch-editor.server": {
98
+ "import": {
99
+ "types": "./dist/esm/launch-editor.server.d.ts",
100
+ "default": "./dist/esm/launch-editor.server.js"
101
+ }
102
+ },
96
103
  "./timing.server": {
97
104
  "import": {
98
105
  "types": "./dist/esm/timing.server.d.ts",
@@ -235,6 +242,7 @@
235
242
  "remark": "^15.0.1",
236
243
  "remark-emoji": "^5.0.1",
237
244
  "remark-gfm": "^4.0.1",
245
+ "shell-quote": "^1.8.3",
238
246
  "shiki": "^3.7.0",
239
247
  "unified": "^11.0.5",
240
248
  "unist-util-remove-position": "^5.0.0",
@@ -247,6 +255,7 @@
247
255
  "@types/node": "^24.0.10",
248
256
  "@types/react": "^19.1.8",
249
257
  "@types/react-dom": "^19.1.6",
258
+ "@types/shell-quote": "^1.7.5",
250
259
  "tshy": "^3.0.2",
251
260
  "vitest": "^3.2.4"
252
261
  },