@lvce-editor/shared-process 0.0.41 → 0.2.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.
- package/config/defaultKeyBindings.json +5 -0
- package/extensions/builtin.language-basics-docker/extension.json +13 -3
- package/extensions/builtin.language-basics-go/extension.json +3 -2
- package/extensions/builtin.language-basics-json/extension.json +2 -1
- package/extensions/builtin.language-basics-json/src/tokenizeJson.js +6 -2
- package/extensions/builtin.language-basics-markdown/src/tokenizeMarkdown.js +288 -11
- package/extensions/builtin.language-basics-perl/README.md +14 -0
- package/extensions/builtin.language-basics-perl/extension.json +12 -0
- package/extensions/builtin.language-basics-perl/src/tokenizePerl.js +31 -0
- package/extensions/builtin.language-basics-plaintext/src/tokenizePlaintext.js +1 -1
- package/extensions/builtin.language-basics-toml/extension.json +10 -2
- package/extensions/builtin.theme-slime/color-theme.json +4 -0
- package/extensions/builtin.vscode-icons/icon-theme.json +12 -0
- package/extensions/builtin.vscode-icons/icons/file_type_light_objidconfig.svg +1 -1
- package/extensions/builtin.vscode-icons/icons/file_type_objidconfig.svg +1 -1
- package/extensions/builtin.vscode-icons/icons/file_type_renovate.svg +1 -1
- package/extensions/builtin.vscode-icons/icons/file_type_truffle.svg +1 -0
- package/extensions/builtin.vscode-icons/icons/file_type_unison.svg +1 -0
- package/package.json +6 -6
- package/src/parts/Command/Command.js +5 -18
- package/src/parts/DirentType/DirentType.js +13 -0
- package/src/parts/Download/Download.js +6 -8
- package/src/parts/ExtensionManagement/ExtensionManagement.js +16 -41
- package/src/parts/ExtensionManagement/ExtensionManagementColorTheme.js +4 -6
- package/src/parts/ExtensionManagement/ExtensionManagementIconTheme.js +4 -6
- package/src/parts/ExtensionManifestStatus/ExtensionManifestStatus.js +3 -0
- package/src/parts/FileSystem/FileSystem.js +33 -74
- package/src/parts/Json/Json.js +7 -55
- package/src/parts/JsonError/JsonError.js +70 -0
- package/src/parts/JsonFile/JsonFile.js +5 -5
- package/src/parts/Native/Native.js +2 -6
- package/src/parts/Preferences/Preferences.js +1 -1
- package/src/parts/RecentlyOpened/RecentlyOpened.ipc.js +5 -0
- package/src/parts/RecentlyOpened/RecentlyOpened.js +52 -0
- package/src/parts/Search/Search.js +9 -3
- package/src/parts/Electron/Electron.ipc.js +0 -18
- package/src/parts/Electron/Electron.js +0 -110
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><title>tyle_type_unison</title><circle cx="16" cy="16" r="14" style="fill:#c6ffde"/><path d="M23.44,12.06a.48.48,0,0,1-.68.68.47.47,0,0,1-.14-.33.48.48,0,0,1,.48-.48.51.51,0,0,1,.34.13ZM20.5,10.53a5.53,5.53,0,0,1,1.05.32.47.47,0,0,1,.25.61.46.46,0,0,1-.43.29l-.18,0h0a4.1,4.1,0,0,0-.86-.27h0a4.31,4.31,0,0,0-.88-.09h0a1.88,1.88,0,0,1-1.62-.94h0A4.84,4.84,0,0,0,16.6,9.05a4.65,4.65,0,0,0-6.54.87.49.49,0,0,1-.37.18.47.47,0,0,1-.47-.47.42.42,0,0,1,.1-.28v0A5.72,5.72,0,0,1,11,7.9,5.58,5.58,0,0,1,18.6,10h0a.91.91,0,0,0,.78.46h0a5.68,5.68,0,0,1,1.09.11Zm-11.58,6v0a.94.94,0,0,0,0-.92v0a5.61,5.61,0,0,1-.55-4.24A.46.46,0,0,1,8.82,11a.48.48,0,0,1,.47.47.5.5,0,0,1,0,.12,4.68,4.68,0,0,0,.46,3.53v0a1.83,1.83,0,0,1,0,1.84l0,0a4.73,4.73,0,0,0-.57,1.71,4.66,4.66,0,0,0,4,5.24h0a.47.47,0,0,1,.4.47v.06a.48.48,0,0,1-.52.4h0a5.77,5.77,0,0,1-2.07-.7A5.61,5.61,0,0,1,8.92,16.52Zm.81.55,0,0h0Zm5.49,7.7a.48.48,0,0,1-.59-.34.47.47,0,0,1,.34-.58l.12,0a.48.48,0,0,1,.13.94Zm4.23-3.15a.93.93,0,0,0-.8.46h0A5.75,5.75,0,0,1,18,23h0l0,0a5.36,5.36,0,0,1-.78.73.47.47,0,0,1-.66-.08.47.47,0,0,1,.09-.66,4.29,4.29,0,0,0,.66-.62h0l0,0a5.11,5.11,0,0,0,.51-.71v0a1.86,1.86,0,0,1,1.62-.93,4.62,4.62,0,0,0,1.79-.36,4.68,4.68,0,0,0,2.53-6.1h0a.58.58,0,0,1,0-.18.47.47,0,0,1,.47-.46.46.46,0,0,1,.43.28,5.61,5.61,0,0,1-5.18,7.76ZM19,12.34l.37,0h0a3.73,3.73,0,0,1,0,7.46,2.75,2.75,0,0,1-.41,0,1.86,1.86,0,0,0-1.83,1.06A3.75,3.75,0,0,1,10,19.32a3.71,3.71,0,0,1,.74-2.23,1.85,1.85,0,0,0,0-2.09l-.13-.19a3.69,3.69,0,0,1-.59-2,3.74,3.74,0,0,1,7.16-1.5A1.87,1.87,0,0,0,19,12.34Zm-7.58,8.43a2.78,2.78,0,0,0,2.41,1.41,2.83,2.83,0,0,0,0-5.65,2.71,2.71,0,0,0-1.39.38A2.85,2.85,0,0,0,11.42,20.77ZM17,17.47a2.78,2.78,0,0,0,2.41,1.41,2.83,2.83,0,0,0,0-5.65,2.71,2.71,0,0,0-1.39.38A2.85,2.85,0,0,0,17,17.47Zm-3.16-1.89a2.83,2.83,0,1,0-2.78-2.83h0a2.82,2.82,0,0,0,2.78,2.83Z" style="fill:#27ae60;fill-rule:evenodd"/></svg>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lvce-editor/shared-process",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -23,11 +23,11 @@
|
|
|
23
23
|
"chokidar": "^3.5.3",
|
|
24
24
|
"debug": "^4.3.4",
|
|
25
25
|
"execa": "^6.1.0",
|
|
26
|
-
"exit-hook": "^3.
|
|
27
|
-
"got": "^12.
|
|
26
|
+
"exit-hook": "^3.1.0",
|
|
27
|
+
"got": "^12.4.1",
|
|
28
28
|
"is-object": "^1.0.2",
|
|
29
29
|
"json-parse-even-better-errors": "^2.3.1",
|
|
30
|
-
"jsonc-parser": "^3.
|
|
30
|
+
"jsonc-parser": "^3.2.0",
|
|
31
31
|
"lines-and-columns": "^2.0.3",
|
|
32
32
|
"open": "^8.4.0",
|
|
33
33
|
"p-queue": "^7.3.0",
|
|
@@ -38,8 +38,8 @@
|
|
|
38
38
|
"verror": "^1.10.1",
|
|
39
39
|
"ws": "^8.8.1",
|
|
40
40
|
"xdg-basedir": "^5.1.0",
|
|
41
|
-
"@lvce-editor/pty-host": "0.0
|
|
42
|
-
"@lvce-editor/extension-host": "0.0
|
|
41
|
+
"@lvce-editor/pty-host": "0.2.0",
|
|
42
|
+
"@lvce-editor/extension-host": "0.2.0"
|
|
43
43
|
},
|
|
44
44
|
"optionalDependencies": {
|
|
45
45
|
"electron-clipboard-ex": "^1.3.3",
|
|
@@ -11,9 +11,9 @@ const MODULE_PREFERENCES = 11
|
|
|
11
11
|
const MODULE_NATIVE = 12
|
|
12
12
|
const MODULE_CLIPBOARD = 13
|
|
13
13
|
const MODULE_TEXT_DOCUMENT = 14
|
|
14
|
-
const MODULE_ELECTRON = 15
|
|
15
14
|
const MODULE_WEBSOCKET_SERVER = 16
|
|
16
15
|
const MODULE_PLATFORM = 17
|
|
16
|
+
const MODULE_RECENTLY_OPENED = 18
|
|
17
17
|
|
|
18
18
|
const commands = Object.create(null)
|
|
19
19
|
const invocables = Object.create(null)
|
|
@@ -48,12 +48,12 @@ const loadModule = (moduleId) => {
|
|
|
48
48
|
return import('../ClipBoard/ClipBoard.ipc.js')
|
|
49
49
|
case MODULE_TEXT_DOCUMENT:
|
|
50
50
|
return import('../TextDocument/TextDocument.ipc.js')
|
|
51
|
-
case MODULE_ELECTRON:
|
|
52
|
-
return import('../Electron/Electron.ipc.js')
|
|
53
51
|
case MODULE_WEBSOCKET_SERVER:
|
|
54
52
|
return import('../WebSocketServer/WebSocketServer.ipc.js')
|
|
55
53
|
case MODULE_PLATFORM:
|
|
56
54
|
return import('../Platform/Platform.ipc.js')
|
|
55
|
+
case MODULE_RECENTLY_OPENED:
|
|
56
|
+
return import('../RecentlyOpened/RecentlyOpened.ipc.js')
|
|
57
57
|
default:
|
|
58
58
|
throw new Error(`unknown module ${moduleId}`)
|
|
59
59
|
}
|
|
@@ -211,21 +211,8 @@ const getModuleId = (commandId) => {
|
|
|
211
211
|
case 'OutputChannel.open':
|
|
212
212
|
case 'OutputChannel.close':
|
|
213
213
|
return MODULE_OUTPUT_CHANNEL
|
|
214
|
-
case '
|
|
215
|
-
|
|
216
|
-
case 'Electron.windowMaximize':
|
|
217
|
-
case 'Electron.windowUnmaximize':
|
|
218
|
-
case 'Electron.windowClose':
|
|
219
|
-
case 'Electron.about':
|
|
220
|
-
case 'Electron.showOpenDialog':
|
|
221
|
-
case 'Electron.windowReload':
|
|
222
|
-
case 'Electron.getPerformanceEntries':
|
|
223
|
-
case 'Electron.crashMainProcess':
|
|
224
|
-
case 'Electron.showMessageBox':
|
|
225
|
-
case 'Electron.windowOpenNew':
|
|
226
|
-
case 'Electron.exit':
|
|
227
|
-
case 'Electron.openProcessExplorer':
|
|
228
|
-
return MODULE_ELECTRON
|
|
214
|
+
case 'RecentlyOpened.addPath':
|
|
215
|
+
return MODULE_RECENTLY_OPENED
|
|
229
216
|
default:
|
|
230
217
|
throw new Error(`[shared-process] command ${commandId} not found`)
|
|
231
218
|
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export const File = 'file'
|
|
2
|
+
|
|
3
|
+
export const Direcory = 'directory'
|
|
4
|
+
|
|
5
|
+
export const Symlink = 'symlink'
|
|
6
|
+
|
|
7
|
+
export const Socket = 'socket'
|
|
8
|
+
|
|
9
|
+
export const BlockDevice = 'block-device'
|
|
10
|
+
|
|
11
|
+
export const CharacterDevice = 'character-device'
|
|
12
|
+
|
|
13
|
+
export const Unknown = 'unknown'
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
+
import got from 'got'
|
|
1
2
|
import { createReadStream, createWriteStream } from 'node:fs'
|
|
2
3
|
import { mkdir, rm } from 'node:fs/promises'
|
|
3
4
|
import { pipeline } from 'node:stream/promises'
|
|
4
5
|
import { createBrotliDecompress } from 'node:zlib'
|
|
5
|
-
import got from 'got'
|
|
6
6
|
import tar from 'tar-fs'
|
|
7
|
-
import
|
|
7
|
+
import VError from 'verror'
|
|
8
8
|
import * as Path from '../Path/Path.js'
|
|
9
9
|
|
|
10
10
|
export const download = async (url, outFile) => {
|
|
@@ -14,12 +14,10 @@ export const download = async (url, outFile) => {
|
|
|
14
14
|
} catch (error) {
|
|
15
15
|
try {
|
|
16
16
|
await rm(outFile)
|
|
17
|
-
} catch {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
message: `Failed to download "${url}"`,
|
|
22
|
-
})
|
|
17
|
+
} catch {
|
|
18
|
+
// ignore
|
|
19
|
+
}
|
|
20
|
+
throw new VError(error, `Failed to download "${url}"`)
|
|
23
21
|
}
|
|
24
22
|
}
|
|
25
23
|
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
+
import isObject from 'is-object'
|
|
1
2
|
import { mkdir, readdir, rename, rm } from 'node:fs/promises'
|
|
2
|
-
import { performance } from 'node:perf_hooks'
|
|
3
3
|
import path from 'node:path'
|
|
4
|
-
import
|
|
4
|
+
import { performance } from 'node:perf_hooks'
|
|
5
5
|
import VError from 'verror'
|
|
6
6
|
import * as Debug from '../Debug/Debug.js'
|
|
7
|
-
import * as Error from '../Error/Error.js'
|
|
8
7
|
import * as ReadJson from '../JsonFile/JsonFile.js'
|
|
9
8
|
import * as Path from '../Path/Path.js'
|
|
10
9
|
import * as Platform from '../Platform/Platform.js'
|
|
11
10
|
import * as Queue from '../Queue/Queue.js'
|
|
11
|
+
import * as ExtensionManifestStatus from '../ExtensionManifestStatus/ExtensionManifestStatus.js'
|
|
12
12
|
|
|
13
13
|
const isLanguageBasics = (extension) => {
|
|
14
14
|
if (extension && extension.id) {
|
|
@@ -61,11 +61,7 @@ export const install = async (id) => {
|
|
|
61
61
|
// type: 'marketplace',
|
|
62
62
|
// })
|
|
63
63
|
} catch (error) {
|
|
64
|
-
throw new
|
|
65
|
-
cause: error,
|
|
66
|
-
code: 'E_EXT_INSTALL_FAILED',
|
|
67
|
-
message: `Failed to install extension "${id}"`,
|
|
68
|
-
})
|
|
64
|
+
throw new VError(error, `Failed to install extension "${id}"`)
|
|
69
65
|
}
|
|
70
66
|
}
|
|
71
67
|
|
|
@@ -78,11 +74,7 @@ export const uninstall = async (id) => {
|
|
|
78
74
|
// if (error.code === 'ENOENT') {
|
|
79
75
|
// return
|
|
80
76
|
// }
|
|
81
|
-
throw new
|
|
82
|
-
cause: error,
|
|
83
|
-
code: 'E_EXT_UNINSTALL_FAILED',
|
|
84
|
-
message: `Failed to uninstall extension "${id}"`,
|
|
85
|
-
})
|
|
77
|
+
throw new VError(error, `Failed to uninstall extension "${id}"`)
|
|
86
78
|
}
|
|
87
79
|
}
|
|
88
80
|
|
|
@@ -97,11 +89,7 @@ export const enable = async (id) => {
|
|
|
97
89
|
Path.join(extensionsPath, id)
|
|
98
90
|
)
|
|
99
91
|
} catch (error) {
|
|
100
|
-
throw new
|
|
101
|
-
cause: error,
|
|
102
|
-
message: `Failed to enable extension "${id}"`,
|
|
103
|
-
code: 'E_EXTENSION_ENABLING_FAILED',
|
|
104
|
-
})
|
|
92
|
+
throw new VError(error, `Failed to enable extension "${id}"`)
|
|
105
93
|
}
|
|
106
94
|
}
|
|
107
95
|
|
|
@@ -116,11 +104,7 @@ export const disable = async (id) => {
|
|
|
116
104
|
Path.join(disabledExtensionsPath, id)
|
|
117
105
|
)
|
|
118
106
|
} catch (error) {
|
|
119
|
-
throw new
|
|
120
|
-
cause: error,
|
|
121
|
-
code: 'E_EXTENSION_DISABLING_FAILED',
|
|
122
|
-
message: `Failed to disable extension ${id}`,
|
|
123
|
-
})
|
|
107
|
+
throw new VError(error, `Failed to disable extension ${id}`)
|
|
124
108
|
}
|
|
125
109
|
}
|
|
126
110
|
|
|
@@ -160,6 +144,8 @@ const isIncludedBuiltinExtension = (dirent) => {
|
|
|
160
144
|
return !SKIPPED.includes(dirent)
|
|
161
145
|
}
|
|
162
146
|
|
|
147
|
+
// TODO pass builtin extensions path from renderer-worker
|
|
148
|
+
// only negative: more messages sent between renderer-worker and shared process on startup
|
|
163
149
|
const getBuiltinExtensionPaths = async () => {
|
|
164
150
|
try {
|
|
165
151
|
const builtinExtensionsPath = Platform.getBuiltinExtensionsPath()
|
|
@@ -192,11 +178,7 @@ const getInstalledExtensionPaths = async () => {
|
|
|
192
178
|
await mkdir(Platform.getExtensionsPath(), { recursive: true })
|
|
193
179
|
return []
|
|
194
180
|
}
|
|
195
|
-
throw new
|
|
196
|
-
cause: error,
|
|
197
|
-
code: 'E_FAILED_TO_LOAD_INSTALLED_EXTENSIONS',
|
|
198
|
-
message: 'Failed to get installed extensions',
|
|
199
|
-
})
|
|
181
|
+
throw new VError(error, 'Failed to get installed extensions')
|
|
200
182
|
}
|
|
201
183
|
}
|
|
202
184
|
|
|
@@ -222,28 +204,21 @@ const getExtensionManifest = async (path) => {
|
|
|
222
204
|
return {
|
|
223
205
|
...json,
|
|
224
206
|
path,
|
|
225
|
-
status:
|
|
207
|
+
status: ExtensionManifestStatus.Resolved,
|
|
226
208
|
}
|
|
227
209
|
} catch (error) {
|
|
228
210
|
const id = inferExtensionId(path)
|
|
229
211
|
return {
|
|
230
212
|
path,
|
|
231
|
-
status:
|
|
232
|
-
reason: new
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
// @ts-ignore
|
|
237
|
-
stack: error.stack,
|
|
238
|
-
}),
|
|
213
|
+
status: ExtensionManifestStatus.Rejected,
|
|
214
|
+
reason: new VError(
|
|
215
|
+
error,
|
|
216
|
+
`Failed to load extension "${id}": Failed to load extension manifest`
|
|
217
|
+
),
|
|
239
218
|
}
|
|
240
219
|
}
|
|
241
220
|
}
|
|
242
221
|
|
|
243
|
-
const isRejected = (promise) => {
|
|
244
|
-
return promise.status === 'rejected'
|
|
245
|
-
}
|
|
246
|
-
|
|
247
222
|
/**
|
|
248
223
|
* @param {string[]} paths
|
|
249
224
|
*/
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import VError from 'verror'
|
|
1
2
|
import * as Error from '../Error/Error.js'
|
|
2
3
|
import * as ReadJson from '../JsonFile/JsonFile.js'
|
|
4
|
+
import * as Path from '../Path/Path.js'
|
|
3
5
|
import * as ExtensionManagement from './ExtensionManagement.js'
|
|
4
6
|
|
|
5
7
|
// TODO test this function
|
|
@@ -14,16 +16,12 @@ export const getColorThemeJson = async (colorThemeId) => {
|
|
|
14
16
|
if (colorTheme.id !== colorThemeId) {
|
|
15
17
|
continue
|
|
16
18
|
}
|
|
17
|
-
const absolutePath =
|
|
19
|
+
const absolutePath = Path.join(extension.path, colorTheme.path)
|
|
18
20
|
try {
|
|
19
21
|
const json = await ReadJson.readJson(absolutePath)
|
|
20
22
|
return json
|
|
21
23
|
} catch (error) {
|
|
22
|
-
throw new
|
|
23
|
-
cause: error,
|
|
24
|
-
code: 'E_COLOR_THEME_COULD_NOT_BE_LOADED',
|
|
25
|
-
message: `Failed to load color theme "${colorThemeId}"`,
|
|
26
|
-
})
|
|
24
|
+
throw new VError(error, `Failed to load color theme "${colorThemeId}"`)
|
|
27
25
|
}
|
|
28
26
|
}
|
|
29
27
|
}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import VError from 'verror'
|
|
1
2
|
import * as Error from '../Error/Error.js'
|
|
2
3
|
import * as ReadJson from '../JsonFile/JsonFile.js'
|
|
4
|
+
import * as Path from '../Path/Path.js'
|
|
3
5
|
import * as ExtensionManagement from './ExtensionManagement.js'
|
|
4
6
|
|
|
5
7
|
export const getIconTheme = async (iconThemeId) => {
|
|
@@ -12,7 +14,7 @@ export const getIconTheme = async (iconThemeId) => {
|
|
|
12
14
|
if (iconTheme.id !== iconThemeId) {
|
|
13
15
|
continue
|
|
14
16
|
}
|
|
15
|
-
const absolutePath =
|
|
17
|
+
const absolutePath = Path.join(extension.path, iconTheme.path)
|
|
16
18
|
try {
|
|
17
19
|
const json = await ReadJson.readJson(absolutePath)
|
|
18
20
|
return {
|
|
@@ -20,11 +22,7 @@ export const getIconTheme = async (iconThemeId) => {
|
|
|
20
22
|
json,
|
|
21
23
|
}
|
|
22
24
|
} catch (error) {
|
|
23
|
-
throw new
|
|
24
|
-
cause: error,
|
|
25
|
-
code: 'E_ICON_THEME_COULD_NOT_BE_LOADED',
|
|
26
|
-
message: `Failed to load icon theme "${iconThemeId}"`,
|
|
27
|
-
})
|
|
25
|
+
throw new VError(error, `Failed to load icon theme "${iconThemeId}"`)
|
|
28
26
|
}
|
|
29
27
|
}
|
|
30
28
|
}
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
// TODO lazyload chokidar and trash (but doesn't work currently because of bug with jest)
|
|
2
2
|
import * as fs from 'node:fs/promises'
|
|
3
3
|
import * as os from 'node:os'
|
|
4
|
-
import
|
|
5
|
-
import * as
|
|
4
|
+
import VError from 'verror'
|
|
5
|
+
import * as DirentType from '../DirentType/DirentType.js'
|
|
6
6
|
import * as Path from '../Path/Path.js'
|
|
7
|
-
import * as Trash from '../Trash/Trash.js'
|
|
8
7
|
import * as Platform from '../Platform/Platform.js'
|
|
9
|
-
import
|
|
8
|
+
import * as Trash from '../Trash/Trash.js'
|
|
10
9
|
|
|
11
10
|
export const state = {
|
|
12
11
|
watcherMap: Object.create(null),
|
|
@@ -27,26 +26,26 @@ export const copy = async (source, target) => {
|
|
|
27
26
|
`Failed to copy "${source}" to "${target}": src and dest cannot be the same`
|
|
28
27
|
)
|
|
29
28
|
}
|
|
30
|
-
throw new
|
|
31
|
-
cause: error,
|
|
32
|
-
code: 'E_FILE_SYSTEM_ERROR',
|
|
33
|
-
message: `Failed to copy "${source}" to "${target}"`,
|
|
34
|
-
category: 'File System Error',
|
|
35
|
-
})
|
|
29
|
+
throw new VError(error, `Failed to copy "${source}" to "${target}"`)
|
|
36
30
|
}
|
|
37
31
|
}
|
|
38
32
|
|
|
33
|
+
// TODO extensions should only be accessed once on startup
|
|
39
34
|
export const readFile = async (path) => {
|
|
35
|
+
// console.info('[shared-process] read file', path)
|
|
40
36
|
try {
|
|
37
|
+
// const start = performance.now()
|
|
38
|
+
// console.time(`read ${path}`)
|
|
41
39
|
const content = await fs.readFile(path, 'utf8')
|
|
40
|
+
// const end = performance.now()
|
|
41
|
+
// console.log('read', path, 'took', (end - start).toFixed(2), 'ms')
|
|
42
|
+
// console.timeEnd(`read ${path}`)
|
|
42
43
|
return content
|
|
43
44
|
} catch (error) {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
category: 'File System Error',
|
|
49
|
-
})
|
|
45
|
+
if (error && error.code === 'ENOENT') {
|
|
46
|
+
throw new VError(`File not found '${path}'`)
|
|
47
|
+
}
|
|
48
|
+
throw new VError(error, `Failed to read file "${path}"`)
|
|
50
49
|
}
|
|
51
50
|
}
|
|
52
51
|
|
|
@@ -56,12 +55,7 @@ export const writeFile = async (path, content) => {
|
|
|
56
55
|
// Queue.add(`writeFile/${path}`, () =>
|
|
57
56
|
await fs.writeFile(path, content)
|
|
58
57
|
} catch (error) {
|
|
59
|
-
throw new
|
|
60
|
-
cause: error,
|
|
61
|
-
code: 'E_FILE_SYSTEM_ERROR',
|
|
62
|
-
message: `Failed to write to file "${path}"`,
|
|
63
|
-
category: 'File System Error',
|
|
64
|
-
})
|
|
58
|
+
throw new VError(error, `Failed to write to file "${path}"`)
|
|
65
59
|
}
|
|
66
60
|
}
|
|
67
61
|
|
|
@@ -70,12 +64,7 @@ export const ensureFile = async (path, content) => {
|
|
|
70
64
|
await fs.mkdir(Path.dirname(path), { recursive: true })
|
|
71
65
|
await fs.writeFile(path, content)
|
|
72
66
|
} catch (error) {
|
|
73
|
-
throw new
|
|
74
|
-
cause: error,
|
|
75
|
-
code: 'E_FILE_SYSTEM_ERROR',
|
|
76
|
-
message: `Failed to write to file "${path}"`,
|
|
77
|
-
category: 'File System Error',
|
|
78
|
-
})
|
|
67
|
+
throw new VError(error, `Failed to write to file "${path}"`)
|
|
79
68
|
}
|
|
80
69
|
}
|
|
81
70
|
|
|
@@ -83,12 +72,7 @@ export const createFile = async (path) => {
|
|
|
83
72
|
try {
|
|
84
73
|
await fs.writeFile(path, '', { flag: 'wx' })
|
|
85
74
|
} catch (error) {
|
|
86
|
-
throw new
|
|
87
|
-
cause: error,
|
|
88
|
-
code: 'E_FILE_SYSTEM_ERROR',
|
|
89
|
-
message: `Failed to create file "${path}"`,
|
|
90
|
-
category: 'File System Error',
|
|
91
|
-
})
|
|
75
|
+
throw new VError(error, `Failed to create file "${path}"`)
|
|
92
76
|
}
|
|
93
77
|
}
|
|
94
78
|
|
|
@@ -96,12 +80,7 @@ export const createFolder = async (path, options) => {
|
|
|
96
80
|
try {
|
|
97
81
|
await fs.mkdir(path, options)
|
|
98
82
|
} catch (error) {
|
|
99
|
-
throw new
|
|
100
|
-
cause: error,
|
|
101
|
-
code: 'E_FILE_SYSTEM_ERROR',
|
|
102
|
-
message: `Failed to create folder "${path}"`,
|
|
103
|
-
category: 'File System Error',
|
|
104
|
-
})
|
|
83
|
+
throw new VError(error, `Failed to create folder "${path}"`)
|
|
105
84
|
}
|
|
106
85
|
}
|
|
107
86
|
|
|
@@ -129,12 +108,7 @@ export const remove = async (path) => {
|
|
|
129
108
|
try {
|
|
130
109
|
await Trash.trash(path)
|
|
131
110
|
} catch (error) {
|
|
132
|
-
throw new
|
|
133
|
-
cause: error,
|
|
134
|
-
code: 'E_FILE_REMOVE_SYSTEM_ERROR',
|
|
135
|
-
message: `Failed to remove "${path}"`,
|
|
136
|
-
category: 'File System Error',
|
|
137
|
-
})
|
|
111
|
+
throw new VError(error, `Failed to remove "${path}"`)
|
|
138
112
|
}
|
|
139
113
|
}
|
|
140
114
|
|
|
@@ -152,24 +126,24 @@ export const exists = async (path) => {
|
|
|
152
126
|
*/
|
|
153
127
|
const getType = (dirent) => {
|
|
154
128
|
if (dirent.isFile()) {
|
|
155
|
-
return
|
|
129
|
+
return DirentType.File
|
|
156
130
|
}
|
|
157
131
|
if (dirent.isDirectory()) {
|
|
158
|
-
return
|
|
132
|
+
return DirentType.Direcory
|
|
159
133
|
}
|
|
160
134
|
if (dirent.isSymbolicLink()) {
|
|
161
|
-
return
|
|
135
|
+
return DirentType.Symlink
|
|
162
136
|
}
|
|
163
137
|
if (dirent.isSocket()) {
|
|
164
|
-
return
|
|
138
|
+
return DirentType.Socket
|
|
165
139
|
}
|
|
166
140
|
if (dirent.isBlockDevice()) {
|
|
167
|
-
return
|
|
141
|
+
return DirentType.BlockDevice
|
|
168
142
|
}
|
|
169
143
|
if (dirent.isCharacterDevice()) {
|
|
170
|
-
return
|
|
144
|
+
return DirentType.CharacterDevice
|
|
171
145
|
}
|
|
172
|
-
return
|
|
146
|
+
return DirentType.Unknown
|
|
173
147
|
}
|
|
174
148
|
|
|
175
149
|
/**
|
|
@@ -188,25 +162,15 @@ export const readDirWithFileTypes = async (path) => {
|
|
|
188
162
|
const prettyDirents = dirents.map(toPrettyDirent)
|
|
189
163
|
return prettyDirents
|
|
190
164
|
} catch (error) {
|
|
191
|
-
throw new
|
|
192
|
-
cause: error,
|
|
193
|
-
code: 'E_FILE_READ_DIR_SYSTEM_ERROR',
|
|
194
|
-
message: `Failed to read directory "${path}"`,
|
|
195
|
-
category: 'File System Error',
|
|
196
|
-
})
|
|
165
|
+
throw new VError(error, `Failed to read directory "${path}"`)
|
|
197
166
|
}
|
|
198
167
|
}
|
|
199
168
|
|
|
200
169
|
export const mkdir = async (path) => {
|
|
201
170
|
try {
|
|
202
|
-
await fs.mkdir(path)
|
|
171
|
+
await fs.mkdir(path, { recursive: true })
|
|
203
172
|
} catch (error) {
|
|
204
|
-
throw new
|
|
205
|
-
cause: error,
|
|
206
|
-
code: 'E_CREATE_DIRECTORY_FAILED',
|
|
207
|
-
message: `Failed to create directory "${path}"`,
|
|
208
|
-
category: 'File System Error',
|
|
209
|
-
})
|
|
173
|
+
throw new VError(error, `Failed to create directory "${path}"`)
|
|
210
174
|
}
|
|
211
175
|
}
|
|
212
176
|
|
|
@@ -214,18 +178,13 @@ export const rename = async (oldPath, newPath) => {
|
|
|
214
178
|
try {
|
|
215
179
|
await fs.rename(oldPath, newPath)
|
|
216
180
|
} catch (error) {
|
|
217
|
-
throw new
|
|
218
|
-
cause: error,
|
|
219
|
-
code: 'E_RENAME_FAILED',
|
|
220
|
-
message: `Failed to rename "${oldPath}" to "${newPath}"`,
|
|
221
|
-
category: 'File System Error',
|
|
222
|
-
})
|
|
181
|
+
throw new VError(error, `Failed to rename "${oldPath}" to "${newPath}"`)
|
|
223
182
|
}
|
|
224
183
|
}
|
|
225
184
|
|
|
226
|
-
export const watch = (path, options) => {
|
|
185
|
+
export const watch = async (path, options) => {
|
|
227
186
|
// let state = 'loading'
|
|
228
|
-
|
|
187
|
+
const chokidar = await import('chokidar')
|
|
229
188
|
const watcher = chokidar.watch(`${path}`, {
|
|
230
189
|
ignoreInitial: true,
|
|
231
190
|
})
|
package/src/parts/Json/Json.js
CHANGED
|
@@ -1,65 +1,17 @@
|
|
|
1
|
-
import fallback from 'json-parse-even-better-errors'
|
|
2
|
-
import { codeFrameColumns } from '@babel/code-frame'
|
|
3
|
-
import { LinesAndColumns } from 'lines-and-columns'
|
|
4
|
-
|
|
5
1
|
// parsing error handling based on https://github.com/sindresorhus/parse-json/blob/main/index.js
|
|
6
2
|
|
|
7
3
|
export const parse = async (string, filePath) => {
|
|
8
4
|
try {
|
|
9
|
-
|
|
10
|
-
return JSON.parse(string)
|
|
11
|
-
} catch (error) {
|
|
12
|
-
fallback(string)
|
|
13
|
-
throw error
|
|
14
|
-
}
|
|
5
|
+
return JSON.parse(string)
|
|
15
6
|
} catch (error) {
|
|
16
|
-
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
if (topMessage.startsWith('Unexpected token')) {
|
|
23
|
-
topMessage = 'JSON parsing error:'
|
|
24
|
-
}
|
|
25
|
-
if (bottomMessage.includes('while parsing "{')) {
|
|
26
|
-
bottomMessage = bottomMessage.slice(
|
|
27
|
-
0,
|
|
28
|
-
bottomMessage.indexOf('while parsing "{')
|
|
29
|
-
)
|
|
30
|
-
}
|
|
31
|
-
if (bottomMessage.includes(' (0x7D) ')) {
|
|
32
|
-
bottomMessage = bottomMessage.replace(' (0x7D) ', ' ')
|
|
33
|
-
}
|
|
34
|
-
bottomMessage = bottomMessage.trim()
|
|
35
|
-
const jsonError = new Error(topMessage)
|
|
36
|
-
if (indexMatch && indexMatch.length > 0) {
|
|
37
|
-
const lines = new LinesAndColumns(string)
|
|
38
|
-
const index = Number(indexMatch[1])
|
|
39
|
-
const location = lines.locationForIndex(index)
|
|
40
|
-
const codeFrame = codeFrameColumns(
|
|
41
|
-
string,
|
|
42
|
-
{ start: { line: location.line + 1, column: location.column + 1 } },
|
|
43
|
-
{ highlightCode: true }
|
|
44
|
-
)
|
|
45
|
-
jsonError.codeFrame = codeFrame
|
|
46
|
-
}
|
|
47
|
-
// console.log({ bottomMessage, message: error.message })
|
|
48
|
-
jsonError.stack = `${bottomMessage}\n at ${filePath}`
|
|
7
|
+
const JsonError = await import('../JsonError/JsonError.js')
|
|
8
|
+
const errorProps = JsonError.getErrorPropsFromError(error, string, filePath)
|
|
9
|
+
const jsonError = new Error(errorProps.message)
|
|
10
|
+
jsonError.stack = errorProps.stack
|
|
11
|
+
// @ts-ignore
|
|
12
|
+
jsonError.codeFrame = errorProps.codeFrame
|
|
49
13
|
throw jsonError
|
|
50
14
|
}
|
|
51
|
-
|
|
52
|
-
// try {
|
|
53
|
-
// return JSON.parse(json)
|
|
54
|
-
// } catch (error) {
|
|
55
|
-
// const parseJsonBetterErrors = await import('parse-json')
|
|
56
|
-
// try {
|
|
57
|
-
// return parseJsonBetterErrors.default(json, filePath)
|
|
58
|
-
// } catch (error) {
|
|
59
|
-
// console.log({ frame: error.codeFrame })
|
|
60
|
-
// throw error
|
|
61
|
-
// }
|
|
62
|
-
// }
|
|
63
15
|
}
|
|
64
16
|
|
|
65
17
|
export const stringify = (value) => {
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { codeFrameColumns } from '@babel/code-frame'
|
|
2
|
+
import { LinesAndColumns } from 'lines-and-columns'
|
|
3
|
+
|
|
4
|
+
// parsing error handling based on https://github.com/sindresorhus/parse-json/blob/main/index.js
|
|
5
|
+
|
|
6
|
+
const emptyError = {
|
|
7
|
+
message: '',
|
|
8
|
+
stack: '',
|
|
9
|
+
codeFrame: '',
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export const getErrorPropsFromError = (error, string, filePath) => {
|
|
13
|
+
const indexMatch = error.message.match(/in JSON at position (\d+)/)
|
|
14
|
+
if (indexMatch && indexMatch.length > 0) {
|
|
15
|
+
const lines = new LinesAndColumns(string)
|
|
16
|
+
const index = Number(indexMatch[1])
|
|
17
|
+
const location = lines.locationForIndex(index)
|
|
18
|
+
if (location) {
|
|
19
|
+
const codeFrame = codeFrameColumns(
|
|
20
|
+
string,
|
|
21
|
+
{ start: { line: location.line + 1, column: location.column + 1 } },
|
|
22
|
+
{ highlightCode: false }
|
|
23
|
+
)
|
|
24
|
+
return {
|
|
25
|
+
codeFrame,
|
|
26
|
+
message: 'Json Parsing Error',
|
|
27
|
+
stack: `at ${filePath}`,
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
if (string.length === 0) {
|
|
32
|
+
return {
|
|
33
|
+
codeFrame: ``,
|
|
34
|
+
message: 'Json Parsing Error: Cannot parse empty string',
|
|
35
|
+
stack: `at ${filePath}`,
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (error.message === 'Unexpected end of JSON input') {
|
|
40
|
+
const lines = new LinesAndColumns(string)
|
|
41
|
+
const index = string.length - 1
|
|
42
|
+
const location = lines.locationForIndex(index)
|
|
43
|
+
if (location) {
|
|
44
|
+
const codeFrame = codeFrameColumns(
|
|
45
|
+
string,
|
|
46
|
+
{ start: { line: location.line + 1, column: location.column + 1 } },
|
|
47
|
+
{ highlightCode: false }
|
|
48
|
+
)
|
|
49
|
+
return {
|
|
50
|
+
codeFrame,
|
|
51
|
+
message: 'Json Parsing Error',
|
|
52
|
+
stack: `at ${filePath}`,
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return {
|
|
57
|
+
codeFrame: ``,
|
|
58
|
+
message: 'Json Parsing Error',
|
|
59
|
+
stack: `at ${filePath}`,
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export const getErrorProps = (string, filePath) => {
|
|
64
|
+
try {
|
|
65
|
+
JSON.parse(string)
|
|
66
|
+
return emptyError
|
|
67
|
+
} catch (error) {
|
|
68
|
+
return getErrorPropsFromError(error, string, filePath)
|
|
69
|
+
}
|
|
70
|
+
}
|