@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.
Files changed (37) hide show
  1. package/config/defaultKeyBindings.json +5 -0
  2. package/extensions/builtin.language-basics-docker/extension.json +13 -3
  3. package/extensions/builtin.language-basics-go/extension.json +3 -2
  4. package/extensions/builtin.language-basics-json/extension.json +2 -1
  5. package/extensions/builtin.language-basics-json/src/tokenizeJson.js +6 -2
  6. package/extensions/builtin.language-basics-markdown/src/tokenizeMarkdown.js +288 -11
  7. package/extensions/builtin.language-basics-perl/README.md +14 -0
  8. package/extensions/builtin.language-basics-perl/extension.json +12 -0
  9. package/extensions/builtin.language-basics-perl/src/tokenizePerl.js +31 -0
  10. package/extensions/builtin.language-basics-plaintext/src/tokenizePlaintext.js +1 -1
  11. package/extensions/builtin.language-basics-toml/extension.json +10 -2
  12. package/extensions/builtin.theme-slime/color-theme.json +4 -0
  13. package/extensions/builtin.vscode-icons/icon-theme.json +12 -0
  14. package/extensions/builtin.vscode-icons/icons/file_type_light_objidconfig.svg +1 -1
  15. package/extensions/builtin.vscode-icons/icons/file_type_objidconfig.svg +1 -1
  16. package/extensions/builtin.vscode-icons/icons/file_type_renovate.svg +1 -1
  17. package/extensions/builtin.vscode-icons/icons/file_type_truffle.svg +1 -0
  18. package/extensions/builtin.vscode-icons/icons/file_type_unison.svg +1 -0
  19. package/package.json +6 -6
  20. package/src/parts/Command/Command.js +5 -18
  21. package/src/parts/DirentType/DirentType.js +13 -0
  22. package/src/parts/Download/Download.js +6 -8
  23. package/src/parts/ExtensionManagement/ExtensionManagement.js +16 -41
  24. package/src/parts/ExtensionManagement/ExtensionManagementColorTheme.js +4 -6
  25. package/src/parts/ExtensionManagement/ExtensionManagementIconTheme.js +4 -6
  26. package/src/parts/ExtensionManifestStatus/ExtensionManifestStatus.js +3 -0
  27. package/src/parts/FileSystem/FileSystem.js +33 -74
  28. package/src/parts/Json/Json.js +7 -55
  29. package/src/parts/JsonError/JsonError.js +70 -0
  30. package/src/parts/JsonFile/JsonFile.js +5 -5
  31. package/src/parts/Native/Native.js +2 -6
  32. package/src/parts/Preferences/Preferences.js +1 -1
  33. package/src/parts/RecentlyOpened/RecentlyOpened.ipc.js +5 -0
  34. package/src/parts/RecentlyOpened/RecentlyOpened.js +52 -0
  35. package/src/parts/Search/Search.js +9 -3
  36. package/src/parts/Electron/Electron.ipc.js +0 -18
  37. 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.41",
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.0.0",
27
- "got": "^12.3.1",
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.1.0",
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.41",
42
- "@lvce-editor/extension-host": "0.0.41"
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 'Electron.toggleDevtools':
215
- case 'Electron.windowMinimize':
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 * as Error from '../Error/Error.js'
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
- throw new Error.OperationalError({
19
- cause: error,
20
- code: 'E_DOWNLOAD_FAILED',
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 isObject from 'is-object'
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 Error.OperationalError({
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 Error.OperationalError({
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 Error.OperationalError({
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 Error.OperationalError({
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 Error.OperationalError({
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: 'fulfilled',
207
+ status: ExtensionManifestStatus.Resolved,
226
208
  }
227
209
  } catch (error) {
228
210
  const id = inferExtensionId(path)
229
211
  return {
230
212
  path,
231
- status: 'rejected',
232
- reason: new Error.OperationalError({
233
- cause: error,
234
- code: 'E_LOADING_EXTENSION_MANIFEST_FAilED',
235
- message: `Failed to load extension "${id}": Failed to load extension manifest`,
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 = `${extension.path}/${colorTheme.path}`
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 Error.OperationalError({
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 = `${extension.path}/${iconTheme.path}`
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 Error.OperationalError({
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
  }
@@ -0,0 +1,3 @@
1
+ export const Resolved = 'resolved'
2
+
3
+ export const Rejected = 'rejected'
@@ -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 chokidar from 'chokidar'
5
- import * as Error from '../Error/Error.js'
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 VError from 'verror'
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 Error.OperationalError({
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
- throw new Error.OperationalError({
45
- cause: error,
46
- code: 'E_FILE_SYSTEM_ERROR',
47
- message: `Failed to read file "${path}"`,
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 Error.OperationalError({
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 Error.OperationalError({
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 Error.OperationalError({
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 Error.OperationalError({
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 Error.OperationalError({
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 'file'
129
+ return DirentType.File
156
130
  }
157
131
  if (dirent.isDirectory()) {
158
- return 'directory'
132
+ return DirentType.Direcory
159
133
  }
160
134
  if (dirent.isSymbolicLink()) {
161
- return 'symlink'
135
+ return DirentType.Symlink
162
136
  }
163
137
  if (dirent.isSocket()) {
164
- return 'socket'
138
+ return DirentType.Socket
165
139
  }
166
140
  if (dirent.isBlockDevice()) {
167
- return 'block-device'
141
+ return DirentType.BlockDevice
168
142
  }
169
143
  if (dirent.isCharacterDevice()) {
170
- return 'character-device'
144
+ return DirentType.CharacterDevice
171
145
  }
172
- return 'unknown'
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 Error.OperationalError({
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 Error.OperationalError({
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 Error.OperationalError({
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
  })
@@ -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
- try {
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
- error.message = error.message.replace(/\n/g, '')
17
- const indexMatch = error.message.match(
18
- /in JSON at position (\d+) while parsing/
19
- )
20
- let topMessage = error.message
21
- let bottomMessage = error.message
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
+ }