@lvce-editor/shared-process 0.13.0 → 0.14.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 +30 -0
- package/config/defaultSettings.json +6 -0
- package/extensions/builtin.language-basics-css/extension.json +2 -1
- package/extensions/builtin.language-basics-css/languageConfiguration.json +21 -0
- package/extensions/builtin.language-basics-css/src/tokenizeCss.js +7 -1
- package/extensions/builtin.language-basics-html/src/tokenizeHtml.js +77 -27
- package/extensions/builtin.language-basics-javascript/src/tokenizeJavaScript.js +29 -1
- package/extensions/builtin.language-basics-json/extension.json +4 -2
- package/extensions/builtin.language-basics-json/src/tokenizeJson.js +3 -0
- package/extensions/builtin.language-basics-jsx/src/tokenizeJsx.js +18 -5
- package/extensions/builtin.language-basics-vue/src/tokenizeVue.js +1 -1
- package/extensions/builtin.language-basics-xml/extension.json +3 -1
- package/package.json +9 -10
- package/src/parts/Assert/Assert.js +1 -6
- package/src/parts/AssertionError/AssertionError.js +6 -0
- package/src/parts/BulkReplacement/BulkReplacement.ipc.js +7 -0
- package/src/parts/BulkReplacement/BulkReplacement.js +20 -0
- package/src/parts/BulkReplacementContent/BulkReplacementContent.js +30 -0
- package/src/parts/ChildProcessError/ChildProcessError.js +45 -0
- package/src/parts/ChromeExtension/ChromeExtension.js +2 -5
- package/src/parts/CleanStack/CleanStack.js +90 -2
- package/src/parts/CliList/CliList.js +3 -0
- package/src/parts/ClipBoard/ClipBoard.js +2 -2
- package/src/parts/ClipBoard/ClipBoardGnome.js +1 -2
- package/src/parts/ClipBoard/ClipBoardNoop.js +2 -2
- package/src/parts/ClipBoard/ClipBoardWindows.js +1 -3
- package/src/parts/Command/Command.js +5 -10
- package/src/parts/Credentials/Credentials.ipc.js +5 -5
- package/src/parts/Credentials/Credentials.js +2 -10
- package/src/parts/Desktop/Desktop.js +22 -0
- package/src/parts/Download/Download.js +2 -2
- package/src/parts/Error/Error.js +1 -1
- package/src/parts/ErrorCodes/ErrorCodes.js +2 -1
- package/src/parts/ErrorHandling/ErrorHandling.js +8 -14
- package/src/parts/ExtensionHost/ExtensionHost.js +1 -2
- package/src/parts/ExtensionHost/ExtensionHostKeyBindings.js +0 -12
- package/src/parts/ExtensionHostRpc/ExtensionHostRpc.js +1 -1
- package/src/parts/ExtensionInstallFromFile/ExtensionInstallFromFile.js +1 -1
- package/src/parts/ExtensionInstallFromGitHub/ExtensionInstallFromGitHub.js +1 -1
- package/src/parts/ExtensionInstallFromUrl/ExtensionInstallFromUrl.js +1 -1
- package/src/parts/ExtensionLink/ExtensionLink.js +0 -19
- package/src/parts/ExtensionList/ExtensionList.js +11 -2
- package/src/parts/ExtensionManagement/ExtensionManagement.js +6 -58
- package/src/parts/ExtensionManagement/ExtensionManagementColorTheme.js +3 -1
- package/src/parts/ExtensionManagement/ExtensionManagementIconTheme.js +1 -1
- package/src/parts/ExtensionManagement/ExtensionManagementLanguages.js +7 -3
- package/src/parts/ExtensionManifestInputType/ExtensionManifestInputType.js +2 -0
- package/src/parts/ExtensionManifests/ExtensionManifests.js +3 -0
- package/src/parts/ExtensionManifests/ExtensionManifestsFromFolder.js +5 -15
- package/src/parts/ExtensionManifests/ExtensionManifestsFromLinkedExtensionsFolder.js +56 -0
- package/src/parts/ExtensionUninstall/ExtensionUninstall.js +18 -0
- package/src/parts/ExtensionUnlink/ExtensionUnlink.js +1 -1
- package/src/parts/Extract/Extract.js +2 -6
- package/src/parts/ExtractZip/ExtractZip.js +1 -1
- package/src/parts/{Error → FileNotFoundError}/FileNotFoundError.js +9 -2
- package/src/parts/FileSystem/FileSystem.js +6 -32
- package/src/parts/FirstNodeWorkerEventType/FirstNodeWorkerEventType.js +5 -0
- package/src/parts/GetDirentType/GetDirentType.js +27 -0
- package/src/parts/GetFirstNodeChildProcessEvent/GetFirstNodeChildProcessEvent.js +39 -0
- package/src/parts/GetFirstNodeWorkerEvent/GetFirstNodeWorkerEvent.js +21 -0
- package/src/parts/GetNewLineIndex/GetNewLineIndex.js +9 -0
- package/src/parts/GetResponse/GetResponse.js +16 -6
- package/src/parts/GetTextSearchRipGrepArgs/GetTextSearchRipGrepArgs.js +14 -0
- package/src/parts/InstallExtension/InstallExtension.ipc.js +6 -0
- package/src/parts/InstallExtension/InstallExtension.js +33 -0
- package/src/parts/IpcParent/IpcParent.js +9 -0
- package/src/parts/IpcParentModule/IpcParentModule.js +12 -0
- package/src/parts/IpcParentType/IpcParentType.js +2 -0
- package/src/parts/IpcParentWithNodeForkedProcess/IpcParentWithNodeForkedProcess.js +49 -0
- package/src/parts/IpcParentWithNodeWorker/IpcParentWithNodeWorker.js +36 -0
- package/src/parts/IsEnoentErrorWindows/IsEnoentErrorWindows.js +3 -0
- package/src/parts/IsIgnoredError/IsIgnoredError.js +14 -0
- package/src/parts/Json/Json.js +3 -5
- package/src/parts/JsonError/JsonError.js +8 -14
- package/src/parts/JsonParsingError/JsonParsingError.js +17 -0
- package/src/parts/Jsonc/Jsonc.js +304 -0
- package/src/parts/JsoncCharCode/JsoncCharCode.js +23 -0
- package/src/parts/JsoncFile/JsoncFile.js +8 -0
- package/src/parts/JsoncTokenType/JsoncTokenType.js +11 -0
- package/src/parts/LimitString/LimitString.js +3 -1
- package/src/parts/MergeStacks/MergeStacks.js +3 -2
- package/src/parts/Module/Module.js +4 -0
- package/src/parts/ModuleId/ModuleId.js +2 -0
- package/src/parts/ModuleMap/ModuleMap.js +4 -0
- package/src/parts/Native/Native.js +1 -1
- package/src/parts/ParentIpc/ParentIpc.js +2 -1
- package/src/parts/Platform/Platform.js +0 -21
- package/src/parts/Preferences/Preferences.js +6 -8
- package/src/parts/PrettyError/PrettyError.js +16 -7
- package/src/parts/PrintPrettyError/PrintPrettyError.js +3 -1
- package/src/parts/RecentlyOpened/RecentlyOpened.js +3 -7
- package/src/parts/RequiresSocket/RequiresSocket.js +1 -0
- package/src/parts/RipGrep/RipGrep.js +1 -1
- package/src/parts/SearchFile/SearchFile.js +4 -9
- package/src/parts/Socket/Socket.js +2 -7
- package/src/parts/Terminal/Terminal.ipc.js +4 -41
- package/src/parts/Terminal/Terminal.js +29 -25
- package/src/parts/TextSearch/TextSearch.js +102 -108
- package/src/parts/ToAbsolutePaths/ToAbsolutePaths.js +9 -0
- package/src/parts/ToTextSearchResult/ToTextSearchResult.js +42 -0
- package/src/parts/Trash/Trash.js +1 -2
- /package/src/parts/{RgPath/RgPath.js → RipGrepPath/RipGrepPath.js} +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as Assert from '../Assert/Assert.js'
|
|
2
2
|
import * as Error from '../Error/Error.js'
|
|
3
3
|
import * as ErrorCodes from '../ErrorCodes/ErrorCodes.js'
|
|
4
4
|
import * as FileSystemWatch from '../FileSystemWatch/FileSystemWatch.js'
|
|
@@ -6,6 +6,7 @@ import * as ReadJson from '../JsonFile/JsonFile.js'
|
|
|
6
6
|
import * as JsonRpcVersion from '../JsonRpcVersion/JsonRpcVersion.js'
|
|
7
7
|
import * as Path from '../Path/Path.js'
|
|
8
8
|
import * as Process from '../Process/Process.js'
|
|
9
|
+
import { VError } from '../VError/VError.js'
|
|
9
10
|
import * as ExtensionManagement from './ExtensionManagement.js'
|
|
10
11
|
|
|
11
12
|
// TODO test this function
|
|
@@ -28,6 +29,7 @@ const getColorThemePath = async (extensions, colorThemeId) => {
|
|
|
28
29
|
}
|
|
29
30
|
|
|
30
31
|
export const getColorThemeJson = async (colorThemeId) => {
|
|
32
|
+
Assert.string(colorThemeId)
|
|
31
33
|
const extensions = await ExtensionManagement.getExtensions()
|
|
32
34
|
const colorThemePath = await getColorThemePath(extensions, colorThemeId)
|
|
33
35
|
if (!colorThemePath) {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import VError from 'verror'
|
|
2
1
|
import * as Error from '../Error/Error.js'
|
|
3
2
|
import * as ErrorCodes from '../ErrorCodes/ErrorCodes.js'
|
|
4
3
|
import * as ReadJson from '../JsonFile/JsonFile.js'
|
|
5
4
|
import * as Path from '../Path/Path.js'
|
|
5
|
+
import { VError } from '../VError/VError.js'
|
|
6
6
|
import * as ExtensionManagement from './ExtensionManagement.js'
|
|
7
7
|
|
|
8
8
|
export const getIconTheme = async (iconThemeId) => {
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
// TODO rename file to languageConfiguration.js
|
|
1
2
|
import { join } from 'node:path'
|
|
2
3
|
import { pathToFileURL } from 'node:url'
|
|
3
|
-
import
|
|
4
|
-
import
|
|
4
|
+
import * as JsonFile from '../JsonFile/JsonFile.js'
|
|
5
|
+
import { VError } from '../VError/VError.js'
|
|
5
6
|
import * as ExtensionManagement from './ExtensionManagement.js'
|
|
6
7
|
|
|
7
8
|
const getExtensionLanguages = (extension) => {
|
|
@@ -70,7 +71,10 @@ export const getLanguageConfiguration = async (languageId) => {
|
|
|
70
71
|
try {
|
|
71
72
|
const extensions = await ExtensionManagement.getExtensions()
|
|
72
73
|
const languageConfigurationPath = getLanguageConfigurationPathFromExtensions(extensions, languageId)
|
|
73
|
-
|
|
74
|
+
if (!languageConfigurationPath) {
|
|
75
|
+
return undefined
|
|
76
|
+
}
|
|
77
|
+
return await JsonFile.readJson(languageConfigurationPath)
|
|
74
78
|
} catch (error) {
|
|
75
79
|
throw new VError(error, `Failed to load language configuration for ${languageId}`)
|
|
76
80
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as ExtensionManifestInputType from '../ExtensionManifestInputType/ExtensionManifestInputType.js'
|
|
2
2
|
import * as ExtensionManifestsGetFromFolder from './ExtensionManifestsFromFolder.js'
|
|
3
|
+
import * as ExtensionManifestsGetFromLinkedExtensionsFolder from './ExtensionManifestsFromLinkedExtensionsFolder.js'
|
|
3
4
|
import * as ExtensionManifestsGetFromOnlyExtension from './ExtensionManifestsFromOnlyExtension.js'
|
|
4
5
|
|
|
5
6
|
const getModule = (type) => {
|
|
@@ -8,6 +9,8 @@ const getModule = (type) => {
|
|
|
8
9
|
return ExtensionManifestsGetFromFolder
|
|
9
10
|
case ExtensionManifestInputType.OnlyExtension:
|
|
10
11
|
return ExtensionManifestsGetFromOnlyExtension
|
|
12
|
+
case ExtensionManifestInputType.LinkedExtensionsFolder:
|
|
13
|
+
return ExtensionManifestsGetFromLinkedExtensionsFolder
|
|
11
14
|
default:
|
|
12
15
|
throw new Error('unsupported input type')
|
|
13
16
|
}
|
|
@@ -1,16 +1,8 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as ErrorCodes from '../ErrorCodes/ErrorCodes.js'
|
|
2
2
|
import * as ExtensionManifest from '../ExtensionManifest/ExtensionManifest.js'
|
|
3
3
|
import * as FileSystem from '../FileSystem/FileSystem.js'
|
|
4
|
-
import * as
|
|
5
|
-
import
|
|
6
|
-
|
|
7
|
-
const toAbsolutePaths = (path, dirents) => {
|
|
8
|
-
const absolutePaths = []
|
|
9
|
-
for (const dirent of dirents) {
|
|
10
|
-
absolutePaths.push(Path.join(path, dirent))
|
|
11
|
-
}
|
|
12
|
-
return absolutePaths
|
|
13
|
-
}
|
|
4
|
+
import * as ToAbsolutePaths from '../ToAbsolutePaths/ToAbsolutePaths.js'
|
|
5
|
+
import { VError } from '../VError/VError.js'
|
|
14
6
|
|
|
15
7
|
export const getExtensionManifests = async (path) => {
|
|
16
8
|
try {
|
|
@@ -18,10 +10,8 @@ export const getExtensionManifests = async (path) => {
|
|
|
18
10
|
return []
|
|
19
11
|
}
|
|
20
12
|
const dirents = await FileSystem.readDir(path)
|
|
21
|
-
const absolutePaths = toAbsolutePaths(path, dirents)
|
|
22
|
-
const manifests = await Promise.all(
|
|
23
|
-
absolutePaths.map(ExtensionManifest.get)
|
|
24
|
-
)
|
|
13
|
+
const absolutePaths = ToAbsolutePaths.toAbsolutePaths(path, dirents)
|
|
14
|
+
const manifests = await Promise.all(absolutePaths.map(ExtensionManifest.get))
|
|
25
15
|
return manifests
|
|
26
16
|
} catch (error) {
|
|
27
17
|
// TODO how to make typescript happy?
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { readlink } from 'fs/promises'
|
|
2
|
+
import * as ErrorCodes from '../ErrorCodes/ErrorCodes.js'
|
|
3
|
+
import * as ExtensionManifest from '../ExtensionManifest/ExtensionManifest.js'
|
|
4
|
+
import * as ExtensionManifestStatus from '../ExtensionManifestStatus/ExtensionManifestStatus.js'
|
|
5
|
+
import * as FileSystem from '../FileSystem/FileSystem.js'
|
|
6
|
+
import * as ToAbsolutePaths from '../ToAbsolutePaths/ToAbsolutePaths.js'
|
|
7
|
+
import { VError } from '../VError/VError.js'
|
|
8
|
+
|
|
9
|
+
const readSymlink = async (absolutePath) => {
|
|
10
|
+
try {
|
|
11
|
+
const info = await readlink(absolutePath)
|
|
12
|
+
return info
|
|
13
|
+
} catch {
|
|
14
|
+
return ''
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const readSymlinks = (absolutePaths) => {
|
|
19
|
+
return Promise.all(absolutePaths.map(readSymlink))
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const mergeWithSymLinks = (manifests, symlinks) => {
|
|
23
|
+
const length = manifests.length
|
|
24
|
+
const merged = []
|
|
25
|
+
for (let i = 0; i < length; i++) {
|
|
26
|
+
const manifest = manifests[i]
|
|
27
|
+
const symlink = symlinks[i]
|
|
28
|
+
if (manifest.status === ExtensionManifestStatus.Rejected) {
|
|
29
|
+
merged.push(manifest)
|
|
30
|
+
} else {
|
|
31
|
+
merged.push({ ...manifest, symlink })
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return merged
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export const getExtensionManifests = async (path) => {
|
|
38
|
+
try {
|
|
39
|
+
if (!path) {
|
|
40
|
+
return []
|
|
41
|
+
}
|
|
42
|
+
const dirents = await FileSystem.readDir(path)
|
|
43
|
+
const absolutePaths = ToAbsolutePaths.toAbsolutePaths(path, dirents)
|
|
44
|
+
const manifests = await Promise.all(absolutePaths.map(ExtensionManifest.get))
|
|
45
|
+
const symlinks = await readSymlinks(absolutePaths)
|
|
46
|
+
const merged = mergeWithSymLinks(manifests, symlinks)
|
|
47
|
+
return merged
|
|
48
|
+
} catch (error) {
|
|
49
|
+
// TODO how to make typescript happy?
|
|
50
|
+
// @ts-ignore
|
|
51
|
+
if (error.code === ErrorCodes.ENOENT) {
|
|
52
|
+
return []
|
|
53
|
+
}
|
|
54
|
+
throw new VError(error, 'Failed to get extension manifests')
|
|
55
|
+
}
|
|
56
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { rm } from 'node:fs/promises'
|
|
2
|
+
import * as Debug from '../Debug/Debug.js'
|
|
3
|
+
import * as Path from '../Path/Path.js'
|
|
4
|
+
import * as Platform from '../Platform/Platform.js'
|
|
5
|
+
import { VError } from '../VError/VError.js'
|
|
6
|
+
|
|
7
|
+
export const uninstall = async (id) => {
|
|
8
|
+
try {
|
|
9
|
+
Debug.debug(`ExtensionManagement#uninstall ${id}`)
|
|
10
|
+
const extensionsPath = Platform.getExtensionsPath()
|
|
11
|
+
await rm(Path.join(extensionsPath, id), { recursive: true })
|
|
12
|
+
} catch (error) {
|
|
13
|
+
// if (error.code === 'ENOENT') {
|
|
14
|
+
// return
|
|
15
|
+
// }
|
|
16
|
+
throw new VError(error, `Failed to uninstall extension "${id}"`)
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import VError from 'verror'
|
|
2
1
|
import * as ExtensionManifest from '../ExtensionManifest/ExtensionManifest.js'
|
|
3
2
|
import * as ExtensionManifestStatus from '../ExtensionManifestStatus/ExtensionManifestStatus.js'
|
|
4
3
|
import * as FileSystem from '../FileSystem/FileSystem.js'
|
|
5
4
|
import * as Path from '../Path/Path.js'
|
|
6
5
|
import * as Platform from '../Platform/Platform.js'
|
|
6
|
+
import { VError } from '../VError/VError.js'
|
|
7
7
|
|
|
8
8
|
export const unlink = async (path) => {
|
|
9
9
|
try {
|
|
@@ -3,16 +3,12 @@ import { mkdir } from 'node:fs/promises'
|
|
|
3
3
|
import { pipeline } from 'node:stream/promises'
|
|
4
4
|
import { createBrotliDecompress, createGunzip } from 'node:zlib'
|
|
5
5
|
import tar from 'tar-fs'
|
|
6
|
-
import VError from '
|
|
6
|
+
import { VError } from '../VError/VError.js'
|
|
7
7
|
|
|
8
8
|
export const extractTarBr = async (inFile, outDir) => {
|
|
9
9
|
try {
|
|
10
10
|
await mkdir(outDir, { recursive: true })
|
|
11
|
-
await pipeline(
|
|
12
|
-
createReadStream(inFile),
|
|
13
|
-
createBrotliDecompress(),
|
|
14
|
-
tar.extract(outDir)
|
|
15
|
-
)
|
|
11
|
+
await pipeline(createReadStream(inFile), createBrotliDecompress(), tar.extract(outDir))
|
|
16
12
|
} catch (error) {
|
|
17
13
|
throw new VError(error, `Failed to extract ${inFile}`)
|
|
18
14
|
}
|
|
@@ -1,9 +1,16 @@
|
|
|
1
|
-
import VError from 'verror'
|
|
2
1
|
import * as ErrorCodes from '../ErrorCodes/ErrorCodes.js'
|
|
2
|
+
import { VError } from '../VError/VError.js'
|
|
3
|
+
|
|
4
|
+
const getDisplayPath = (path) => {
|
|
5
|
+
if (path === '') {
|
|
6
|
+
return '<empty string>'
|
|
7
|
+
}
|
|
8
|
+
return path
|
|
9
|
+
}
|
|
3
10
|
|
|
4
11
|
export class FileNotFoundError extends VError {
|
|
5
12
|
constructor(path) {
|
|
6
|
-
super(`File not found '${path}'`)
|
|
13
|
+
super(`File not found: '${getDisplayPath(path)}'`)
|
|
7
14
|
this.name = 'FileNotFoundError'
|
|
8
15
|
this.code = ErrorCodes.ENOENT
|
|
9
16
|
}
|
|
@@ -1,14 +1,14 @@
|
|
|
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
|
|
6
|
-
import { FileNotFoundError } from '../Error/FileNotFoundError.js'
|
|
4
|
+
import * as EncodingType from '../EncodingType/EncodingType.js'
|
|
5
|
+
import { FileNotFoundError } from '../FileNotFoundError/FileNotFoundError.js'
|
|
7
6
|
import * as ErrorCodes from '../ErrorCodes/ErrorCodes.js'
|
|
7
|
+
import * as GetDirentType from '../GetDirentType/GetDirentType.js'
|
|
8
8
|
import * as Path from '../Path/Path.js'
|
|
9
9
|
import * as Platform from '../Platform/Platform.js'
|
|
10
10
|
import * as Trash from '../Trash/Trash.js'
|
|
11
|
-
import
|
|
11
|
+
import { VError } from '../VError/VError.js'
|
|
12
12
|
|
|
13
13
|
export const state = {
|
|
14
14
|
watcherMap: Object.create(null),
|
|
@@ -132,39 +132,13 @@ export const exists = async (path) => {
|
|
|
132
132
|
}
|
|
133
133
|
}
|
|
134
134
|
|
|
135
|
-
/**
|
|
136
|
-
* @param {import('fs').Dirent|import('fs').StatsBase} dirent
|
|
137
|
-
*/
|
|
138
|
-
const getType = (dirent) => {
|
|
139
|
-
if (dirent.isFile()) {
|
|
140
|
-
return DirentType.File
|
|
141
|
-
}
|
|
142
|
-
if (dirent.isDirectory()) {
|
|
143
|
-
return DirentType.Directory
|
|
144
|
-
}
|
|
145
|
-
if (dirent.isSymbolicLink()) {
|
|
146
|
-
return DirentType.Symlink
|
|
147
|
-
}
|
|
148
|
-
if (dirent.isSocket()) {
|
|
149
|
-
return DirentType.Socket
|
|
150
|
-
}
|
|
151
|
-
if (dirent.isBlockDevice()) {
|
|
152
|
-
return DirentType.BlockDevice
|
|
153
|
-
}
|
|
154
|
-
if (dirent.isCharacterDevice()) {
|
|
155
|
-
return DirentType.CharacterDevice
|
|
156
|
-
}
|
|
157
|
-
console.log({ dirent })
|
|
158
|
-
return DirentType.Unknown
|
|
159
|
-
}
|
|
160
|
-
|
|
161
135
|
/**
|
|
162
136
|
* @param {import('fs').Dirent} dirent
|
|
163
137
|
*/
|
|
164
138
|
const toPrettyDirent = (dirent) => {
|
|
165
139
|
return {
|
|
166
140
|
name: dirent.name,
|
|
167
|
-
type:
|
|
141
|
+
type: GetDirentType.getDirentType(dirent),
|
|
168
142
|
}
|
|
169
143
|
}
|
|
170
144
|
|
|
@@ -264,7 +238,7 @@ export const getRealPath = async (path) => {
|
|
|
264
238
|
// TODO handle error
|
|
265
239
|
export const stat = async (path) => {
|
|
266
240
|
const stats = await fs.stat(path)
|
|
267
|
-
const type =
|
|
241
|
+
const type = GetDirentType.getDirentType(stats)
|
|
268
242
|
return type
|
|
269
243
|
}
|
|
270
244
|
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import * as DirentType from '../DirentType/DirentType.js'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @param {import('fs').Dirent|import('fs').StatsBase} dirent
|
|
5
|
+
*/
|
|
6
|
+
export const getDirentType = (dirent) => {
|
|
7
|
+
if (dirent.isFile()) {
|
|
8
|
+
return DirentType.File
|
|
9
|
+
}
|
|
10
|
+
if (dirent.isDirectory()) {
|
|
11
|
+
return DirentType.Directory
|
|
12
|
+
}
|
|
13
|
+
if (dirent.isSymbolicLink()) {
|
|
14
|
+
return DirentType.Symlink
|
|
15
|
+
}
|
|
16
|
+
if (dirent.isSocket()) {
|
|
17
|
+
return DirentType.Socket
|
|
18
|
+
}
|
|
19
|
+
if (dirent.isBlockDevice()) {
|
|
20
|
+
return DirentType.BlockDevice
|
|
21
|
+
}
|
|
22
|
+
if (dirent.isCharacterDevice()) {
|
|
23
|
+
return DirentType.CharacterDevice
|
|
24
|
+
}
|
|
25
|
+
console.log({ dirent })
|
|
26
|
+
return DirentType.Unknown
|
|
27
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import * as FirstNodeWorkerEventType from '../FirstNodeWorkerEventType/FirstNodeWorkerEventType.js'
|
|
2
|
+
|
|
3
|
+
export const getFirstNodeChildProcessEvent = async (childProcess) => {
|
|
4
|
+
const { type, event, stdout, stderr } = await new Promise((resolve, reject) => {
|
|
5
|
+
let stderr = ''
|
|
6
|
+
let stdout = ''
|
|
7
|
+
const cleanup = () => {
|
|
8
|
+
childProcess.stderr.off('data', handleStdErrData)
|
|
9
|
+
childProcess.stdout.off('data', handleStdoutData)
|
|
10
|
+
childProcess.off('message', handleMessage)
|
|
11
|
+
childProcess.off('exit', handleExit)
|
|
12
|
+
childProcess.off('error', handleError)
|
|
13
|
+
}
|
|
14
|
+
const handleStdErrData = (data) => {
|
|
15
|
+
stderr += data
|
|
16
|
+
}
|
|
17
|
+
const handleStdoutData = (data) => {
|
|
18
|
+
stdout += data
|
|
19
|
+
}
|
|
20
|
+
const handleMessage = (event) => {
|
|
21
|
+
cleanup()
|
|
22
|
+
resolve({ type: FirstNodeWorkerEventType.Message, event, stdout, stderr })
|
|
23
|
+
}
|
|
24
|
+
const handleExit = (event) => {
|
|
25
|
+
cleanup()
|
|
26
|
+
resolve({ type: FirstNodeWorkerEventType.Exit, event, stdout, stderr })
|
|
27
|
+
}
|
|
28
|
+
const handleError = (event) => {
|
|
29
|
+
cleanup()
|
|
30
|
+
resolve({ type: FirstNodeWorkerEventType.Error, event, stdout, stderr })
|
|
31
|
+
}
|
|
32
|
+
childProcess.stderr.on('data', handleStdErrData)
|
|
33
|
+
childProcess.stdout.on('data', handleStdoutData)
|
|
34
|
+
childProcess.on('message', handleMessage)
|
|
35
|
+
childProcess.on('exit', handleExit)
|
|
36
|
+
childProcess.on('error', handleError)
|
|
37
|
+
})
|
|
38
|
+
return { type, event, stdout, stderr }
|
|
39
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import * as FirstNodeWorkerEventType from '../FirstNodeWorkerEventType/FirstNodeWorkerEventType.js'
|
|
2
|
+
|
|
3
|
+
export const getFirstNodeWorkerEvent = async (worker) => {
|
|
4
|
+
const { type, event } = await new Promise((resolve, reject) => {
|
|
5
|
+
const cleanup = () => {
|
|
6
|
+
worker.off('exit', handleExit)
|
|
7
|
+
worker.off('error', handleError)
|
|
8
|
+
}
|
|
9
|
+
const handleExit = (event) => {
|
|
10
|
+
cleanup()
|
|
11
|
+
resolve({ type: FirstNodeWorkerEventType.Exit, event })
|
|
12
|
+
}
|
|
13
|
+
const handleError = (event) => {
|
|
14
|
+
cleanup()
|
|
15
|
+
resolve({ type: FirstNodeWorkerEventType.Error, event })
|
|
16
|
+
}
|
|
17
|
+
worker.on('exit', handleExit)
|
|
18
|
+
worker.on('error', handleError)
|
|
19
|
+
})
|
|
20
|
+
return { type, event }
|
|
21
|
+
}
|
|
@@ -1,24 +1,31 @@
|
|
|
1
1
|
import * as Command from '../Command/Command.js'
|
|
2
|
+
import { CommandNotFoundError } from '../CommandNotFoundError/CommandNotFoundError.js'
|
|
2
3
|
import * as ErrorCodes from '../ErrorCodes/ErrorCodes.js'
|
|
3
4
|
import * as JsonRpcErrorCode from '../JsonRpcErrorCode/JsonRpcErrorCode.js'
|
|
4
5
|
import * as JsonRpcVersion from '../JsonRpcVersion/JsonRpcVersion.js'
|
|
5
6
|
import * as PrettyError from '../PrettyError/PrettyError.js'
|
|
6
7
|
import * as PrintPrettyError from '../PrintPrettyError/PrintPrettyError.js'
|
|
7
|
-
import
|
|
8
|
+
import * as RequiresSocket from '../RequiresSocket/RequiresSocket.js'
|
|
9
|
+
|
|
10
|
+
const shouldLogError = (error) => {
|
|
11
|
+
if (error && error.code === ErrorCodes.ENOENT) {
|
|
12
|
+
return false
|
|
13
|
+
}
|
|
14
|
+
return true
|
|
15
|
+
}
|
|
8
16
|
|
|
9
17
|
export const getResponse = async (message, handle) => {
|
|
10
18
|
try {
|
|
11
|
-
const result = requiresSocket(message.method)
|
|
19
|
+
const result = RequiresSocket.requiresSocket(message.method)
|
|
12
20
|
? await Command.execute(message.method, handle, ...message.params)
|
|
13
21
|
: await Command.execute(message.method, ...message.params)
|
|
14
|
-
|
|
15
22
|
return {
|
|
16
23
|
jsonrpc: JsonRpcVersion.Two,
|
|
17
24
|
id: message.id,
|
|
18
25
|
result: result ?? null,
|
|
19
26
|
}
|
|
20
27
|
} catch (error) {
|
|
21
|
-
if (error && error instanceof
|
|
28
|
+
if (error && error instanceof CommandNotFoundError) {
|
|
22
29
|
return {
|
|
23
30
|
jsonrpc: JsonRpcVersion.Two,
|
|
24
31
|
id: message.id,
|
|
@@ -29,14 +36,16 @@ export const getResponse = async (message, handle) => {
|
|
|
29
36
|
},
|
|
30
37
|
}
|
|
31
38
|
}
|
|
32
|
-
|
|
33
|
-
if (error && error instanceof Error && error.code === ErrorCodes.ENOENT) {
|
|
39
|
+
if (!shouldLogError(error)) {
|
|
34
40
|
return {
|
|
35
41
|
jsonrpc: JsonRpcVersion.Two,
|
|
36
42
|
id: message.id,
|
|
37
43
|
error: {
|
|
38
44
|
code: JsonRpcErrorCode.Custom,
|
|
39
45
|
message: `${error}`,
|
|
46
|
+
data: {
|
|
47
|
+
code: error.code,
|
|
48
|
+
},
|
|
40
49
|
},
|
|
41
50
|
}
|
|
42
51
|
}
|
|
@@ -51,6 +60,7 @@ export const getResponse = async (message, handle) => {
|
|
|
51
60
|
data: {
|
|
52
61
|
stack: prettyError.stack,
|
|
53
62
|
codeFrame: prettyError.codeFrame,
|
|
63
|
+
type: prettyError.type,
|
|
54
64
|
},
|
|
55
65
|
},
|
|
56
66
|
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export const getRipGrepArgs = ({ threads, isCaseSensitive, searchString }) => {
|
|
2
|
+
const ripGrepArgs = ['--smart-case', '--stats', '--json']
|
|
3
|
+
ripGrepArgs.push('--threads', `${threads}`)
|
|
4
|
+
if (isCaseSensitive) {
|
|
5
|
+
ripGrepArgs.push('--case-sensitive')
|
|
6
|
+
} else {
|
|
7
|
+
ripGrepArgs.push('--ignore-case')
|
|
8
|
+
}
|
|
9
|
+
ripGrepArgs.push('--fixed-strings')
|
|
10
|
+
ripGrepArgs.push('--')
|
|
11
|
+
ripGrepArgs.push(searchString)
|
|
12
|
+
ripGrepArgs.push('.')
|
|
13
|
+
return ripGrepArgs
|
|
14
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import * as Debug from '../Debug/Debug.js'
|
|
2
|
+
import * as Download from '../Download/Download.js'
|
|
3
|
+
import * as Extract from '../Extract/Extract.js'
|
|
4
|
+
import * as Path from '../Path/Path.js'
|
|
5
|
+
import * as Platform from '../Platform/Platform.js'
|
|
6
|
+
import * as Queue from '../Queue/Queue.js'
|
|
7
|
+
import { VError } from '../VError/VError.js'
|
|
8
|
+
|
|
9
|
+
export const installExtension = async (id) => {
|
|
10
|
+
// TODO this should be a stateless function, renderer-worker should have info on marketplace url
|
|
11
|
+
// TODO use command.execute
|
|
12
|
+
try {
|
|
13
|
+
const marketplaceUrl = Platform.getMarketplaceUrl()
|
|
14
|
+
Debug.debug(`ExtensionManagement#install ${id}`)
|
|
15
|
+
const cachedExtensionsPath = Platform.getCachedExtensionsPath()
|
|
16
|
+
const extensionsPath = Platform.getExtensionsPath()
|
|
17
|
+
// TODO maybe a queue is over engineering here
|
|
18
|
+
await Queue.add('download', async () => {
|
|
19
|
+
Debug.debug(`ExtensionManagement#download ${id}`)
|
|
20
|
+
// TODO use command.execute
|
|
21
|
+
await Download.download(`${marketplaceUrl}/download/${id}`, Path.join(cachedExtensionsPath, `${id}.tar.br`))
|
|
22
|
+
Debug.debug(`ExtensionManagement#extract ${id}`)
|
|
23
|
+
await Extract.extractTarBr(Path.join(cachedExtensionsPath, `${id}.tar.br`), Path.join(extensionsPath, id))
|
|
24
|
+
})
|
|
25
|
+
// TODO should this be here? (probably not)
|
|
26
|
+
// await ExtensionHost.enableExtension({
|
|
27
|
+
// id,
|
|
28
|
+
// type: 'marketplace',
|
|
29
|
+
// })
|
|
30
|
+
} catch (error) {
|
|
31
|
+
throw new VError(error, `Failed to install extension "${id}"`)
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import * as IpcParentModule from '../IpcParentModule/IpcParentModule.js'
|
|
2
|
+
|
|
3
|
+
export const create = async ({ method, ...options }) => {
|
|
4
|
+
const module = await IpcParentModule.getModule(method)
|
|
5
|
+
// @ts-ignore
|
|
6
|
+
const rawIpc = await module.create(options)
|
|
7
|
+
const ipc = module.wrap(rawIpc)
|
|
8
|
+
return ipc
|
|
9
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import * as IpcParentType from '../IpcParentType/IpcParentType.js'
|
|
2
|
+
|
|
3
|
+
export const getModule = (method) => {
|
|
4
|
+
switch (method) {
|
|
5
|
+
case IpcParentType.NodeWorker:
|
|
6
|
+
return import('../IpcParentWithNodeWorker/IpcParentWithNodeWorker.js')
|
|
7
|
+
case IpcParentType.NodeForkedProcess:
|
|
8
|
+
return import('../IpcParentWithNodeForkedProcess/IpcParentWithNodeForkedProcess.js')
|
|
9
|
+
default:
|
|
10
|
+
throw new Error('unexpected ipc type')
|
|
11
|
+
}
|
|
12
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import * as Assert from '../Assert/Assert.js'
|
|
2
|
+
import { fork } from 'node:child_process'
|
|
3
|
+
import * as GetFirstNodeChildProcessEvent from '../GetFirstNodeChildProcessEvent/GetFirstNodeChildProcessEvent.js'
|
|
4
|
+
import * as FirstNodeWorkerEventType from '../FirstNodeWorkerEventType/FirstNodeWorkerEventType.js'
|
|
5
|
+
import { ChildProcessError } from '../ChildProcessError/ChildProcessError.js'
|
|
6
|
+
import { VError } from '../VError/VError.js'
|
|
7
|
+
|
|
8
|
+
export const create = async ({ path, argv = [], env, execArgv = [], stdio = 'inherit', name = 'child process' }) => {
|
|
9
|
+
try {
|
|
10
|
+
Assert.string(path)
|
|
11
|
+
const childProcess = fork(path, argv, {
|
|
12
|
+
env,
|
|
13
|
+
execArgv,
|
|
14
|
+
stdio: 'pipe',
|
|
15
|
+
})
|
|
16
|
+
const { type, event, stdout, stderr } = await GetFirstNodeChildProcessEvent.getFirstNodeChildProcessEvent(childProcess)
|
|
17
|
+
if (type === FirstNodeWorkerEventType.Exit) {
|
|
18
|
+
throw new ChildProcessError(stderr)
|
|
19
|
+
}
|
|
20
|
+
if (type === FirstNodeWorkerEventType.Error) {
|
|
21
|
+
throw new Error(`child process had an error ${event}`)
|
|
22
|
+
}
|
|
23
|
+
if (stdio === 'inherit' && childProcess.stdout && childProcess.stderr) {
|
|
24
|
+
childProcess.stdout.pipe(process.stdout)
|
|
25
|
+
childProcess.stderr.pipe(process.stderr)
|
|
26
|
+
}
|
|
27
|
+
return childProcess
|
|
28
|
+
} catch (error) {
|
|
29
|
+
throw new VError(error, `Failed to launch ${name}`)
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export const wrap = (childProcess) => {
|
|
34
|
+
return {
|
|
35
|
+
childProcess,
|
|
36
|
+
on(event, listener) {
|
|
37
|
+
this.childProcess.on(event, listener)
|
|
38
|
+
},
|
|
39
|
+
send(message) {
|
|
40
|
+
this.childProcess.send(message)
|
|
41
|
+
},
|
|
42
|
+
sendAndTransfer(message, transfer) {
|
|
43
|
+
throw new Error('transfer is not supported')
|
|
44
|
+
},
|
|
45
|
+
dispose() {
|
|
46
|
+
this.childProcess.kill()
|
|
47
|
+
},
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { Worker } from 'node:worker_threads'
|
|
2
|
+
import * as Assert from '../Assert/Assert.js'
|
|
3
|
+
import * as FirstNodeWorkerEventType from '../FirstNodeWorkerEventType/FirstNodeWorkerEventType.js'
|
|
4
|
+
import * as GetFirstNodeWorkerEvent from '../GetFirstNodeWorkerEvent/GetFirstNodeWorkerEvent.js'
|
|
5
|
+
|
|
6
|
+
export const create = async ({ path, argv, env, execArgv }) => {
|
|
7
|
+
Assert.string(path)
|
|
8
|
+
const worker = new Worker(path, {
|
|
9
|
+
argv,
|
|
10
|
+
env,
|
|
11
|
+
execArgv,
|
|
12
|
+
})
|
|
13
|
+
const { type, event } = await GetFirstNodeWorkerEvent.getFirstNodeWorkerEvent(worker)
|
|
14
|
+
if (type === FirstNodeWorkerEventType.Error) {
|
|
15
|
+
throw event
|
|
16
|
+
}
|
|
17
|
+
return worker
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export const wrap = (worker) => {
|
|
21
|
+
return {
|
|
22
|
+
worker,
|
|
23
|
+
on(event, listener) {
|
|
24
|
+
this.worker.on(event, listener)
|
|
25
|
+
},
|
|
26
|
+
send(message) {
|
|
27
|
+
this.worker.postMessage(message)
|
|
28
|
+
},
|
|
29
|
+
sendAndTransfer(message, transfer) {
|
|
30
|
+
this.worker.postMessage(message, transfer)
|
|
31
|
+
},
|
|
32
|
+
dispose() {
|
|
33
|
+
this.worker.terminate()
|
|
34
|
+
},
|
|
35
|
+
}
|
|
36
|
+
}
|