@inlang/sdk 0.9.0 → 0.11.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 (51) hide show
  1. package/dist/adapter/solidAdapter.test.js +12 -8
  2. package/dist/errors.d.ts +18 -5
  3. package/dist/errors.d.ts.map +1 -1
  4. package/dist/errors.js +12 -10
  5. package/dist/loadProject.d.ts +4 -1
  6. package/dist/loadProject.d.ts.map +1 -1
  7. package/dist/loadProject.js +22 -11
  8. package/dist/loadProject.test.js +122 -43
  9. package/dist/resolve-modules/createNodeishFsWithAbsolutePaths.d.ts +6 -0
  10. package/dist/resolve-modules/createNodeishFsWithAbsolutePaths.d.ts.map +1 -0
  11. package/dist/resolve-modules/createNodeishFsWithAbsolutePaths.js +20 -0
  12. package/dist/resolve-modules/createNodeishFsWithAbsolutePaths.test.d.ts +2 -0
  13. package/dist/resolve-modules/createNodeishFsWithAbsolutePaths.test.d.ts.map +1 -0
  14. package/dist/resolve-modules/createNodeishFsWithAbsolutePaths.test.js +85 -0
  15. package/dist/resolve-modules/errors.d.ts +6 -5
  16. package/dist/resolve-modules/errors.d.ts.map +1 -1
  17. package/dist/resolve-modules/errors.js +10 -8
  18. package/dist/resolve-modules/import.d.ts.map +1 -1
  19. package/dist/resolve-modules/import.js +5 -5
  20. package/dist/resolve-modules/message-lint-rules/errors.d.ts +5 -4
  21. package/dist/resolve-modules/message-lint-rules/errors.d.ts.map +1 -1
  22. package/dist/resolve-modules/message-lint-rules/errors.js +2 -4
  23. package/dist/resolve-modules/message-lint-rules/resolveMessageLintRules.d.ts.map +1 -1
  24. package/dist/resolve-modules/message-lint-rules/resolveMessageLintRules.js +4 -2
  25. package/dist/resolve-modules/plugins/errors.d.ts +35 -28
  26. package/dist/resolve-modules/plugins/errors.d.ts.map +1 -1
  27. package/dist/resolve-modules/plugins/errors.js +23 -30
  28. package/dist/resolve-modules/plugins/resolvePlugins.d.ts.map +1 -1
  29. package/dist/resolve-modules/plugins/resolvePlugins.js +15 -14
  30. package/dist/resolve-modules/plugins/types.d.ts +2 -2
  31. package/dist/resolve-modules/plugins/types.d.ts.map +1 -1
  32. package/dist/resolve-modules/resolveModules.d.ts.map +1 -1
  33. package/dist/resolve-modules/resolveModules.js +5 -4
  34. package/dist/resolve-modules/resolveModules.test.js +2 -2
  35. package/dist/test-utilities/createMessage.d.ts +1 -1
  36. package/package.json +1 -1
  37. package/src/adapter/solidAdapter.test.ts +12 -8
  38. package/src/errors.ts +19 -10
  39. package/src/loadProject.test.ts +132 -43
  40. package/src/loadProject.ts +30 -18
  41. package/src/resolve-modules/createNodeishFsWithAbsolutePaths.test.ts +102 -0
  42. package/src/resolve-modules/createNodeishFsWithAbsolutePaths.ts +30 -0
  43. package/src/resolve-modules/errors.ts +14 -8
  44. package/src/resolve-modules/import.ts +5 -5
  45. package/src/resolve-modules/message-lint-rules/errors.ts +5 -5
  46. package/src/resolve-modules/message-lint-rules/resolveMessageLintRules.ts +4 -2
  47. package/src/resolve-modules/plugins/errors.ts +34 -36
  48. package/src/resolve-modules/plugins/resolvePlugins.ts +17 -46
  49. package/src/resolve-modules/plugins/types.ts +2 -2
  50. package/src/resolve-modules/resolveModules.test.ts +2 -2
  51. package/src/resolve-modules/resolveModules.ts +5 -6
@@ -0,0 +1,102 @@
1
+ import type { NodeishFilesystemSubset } from "@inlang/plugin"
2
+ import { describe, it, expect } from "vitest"
3
+ import { createNodeishFsWithAbsolutePaths } from "./createNodeishFsWithAbsolutePaths.js"
4
+
5
+ describe("createNodeishFsWithAbsolutePaths", () => {
6
+ it("throws an error if basePath is not an absolute path", () => {
7
+ const invalidBasePath = "relative/path"
8
+ const nodeishFs: NodeishFilesystemSubset = {
9
+ // @ts-expect-error
10
+ readFile: async () => Promise.resolve(new Uint8Array(0)),
11
+ readdir: async () => Promise.resolve([]),
12
+ mkdir: async () => Promise.resolve(""),
13
+ writeFile: async () => Promise.resolve(),
14
+ }
15
+
16
+ expect(() =>
17
+ createNodeishFsWithAbsolutePaths({ basePath: invalidBasePath, nodeishFs })
18
+ ).toThrowError("The argument `settingsFilePath` of `loadProject()` must be an absolute path.")
19
+ })
20
+
21
+ it("intercepts paths correctly for readFile", async () => {
22
+ const basePath = "/absolute/path"
23
+ const filePath = "file.txt"
24
+ const expectedPath = "/absolute/path/file.txt"
25
+
26
+ const nodeishFs: NodeishFilesystemSubset = {
27
+ // @ts-expect-error
28
+ readFile: async (path) => {
29
+ expect(path).toBe(expectedPath)
30
+ return Promise.resolve(new Uint8Array(0))
31
+ },
32
+ readdir: async () => Promise.resolve([]),
33
+ mkdir: async () => Promise.resolve(""),
34
+ writeFile: async () => Promise.resolve(),
35
+ }
36
+
37
+ const interceptedFs = createNodeishFsWithAbsolutePaths({ basePath, nodeishFs })
38
+ await interceptedFs.readFile(filePath, { encoding: "utf-8" })
39
+ })
40
+
41
+ it("intercepts paths correctly for readdir", async () => {
42
+ const basePath = "/absolute/path"
43
+ const dirPath = "dir"
44
+ const expectedPath = "/absolute/path/dir"
45
+
46
+ const nodeishFs: NodeishFilesystemSubset = {
47
+ // @ts-expect-error
48
+ readFile: async () => Promise.resolve(new Uint8Array(0)),
49
+ readdir: async (path) => {
50
+ expect(path).toBe(expectedPath)
51
+ return Promise.resolve([])
52
+ },
53
+ mkdir: async () => Promise.resolve(""),
54
+ writeFile: async () => Promise.resolve(),
55
+ }
56
+
57
+ const interceptedFs = createNodeishFsWithAbsolutePaths({ basePath, nodeishFs })
58
+ await interceptedFs.readdir(dirPath)
59
+ })
60
+
61
+ it("intercepts paths correctly for mkdir", async () => {
62
+ const basePath = "/absolute/path"
63
+ const dirPath = "newDir"
64
+ const expectedPath = "/absolute/path/newDir"
65
+
66
+ const nodeishFs: NodeishFilesystemSubset = {
67
+ // @ts-expect-error
68
+ readFile: async () => Promise.resolve(new Uint8Array(0)),
69
+ readdir: async () => Promise.resolve([]),
70
+ mkdir: async (path) => {
71
+ expect(path).toBe(expectedPath)
72
+ return Promise.resolve("")
73
+ },
74
+ writeFile: async () => Promise.resolve(),
75
+ }
76
+
77
+ const interceptedFs = createNodeishFsWithAbsolutePaths({ basePath, nodeishFs })
78
+ await interceptedFs.mkdir(dirPath)
79
+ })
80
+
81
+ it("intercepts paths correctly for writeFile", async () => {
82
+ const basePath = "/absolute/path"
83
+ const filePath = "file.txt"
84
+ const expectedPath = "/absolute/path/file.txt"
85
+ const data = "Hello, World!"
86
+
87
+ const nodeishFs: NodeishFilesystemSubset = {
88
+ // @ts-expect-error
89
+ readFile: async () => Promise.resolve(new Uint8Array(0)),
90
+ readdir: async () => Promise.resolve([]),
91
+ mkdir: async () => Promise.resolve(""),
92
+ writeFile: async (path, content) => {
93
+ expect(path).toBe(expectedPath)
94
+ expect(content).toBe(data)
95
+ return Promise.resolve()
96
+ },
97
+ }
98
+
99
+ const interceptedFs = createNodeishFsWithAbsolutePaths({ basePath, nodeishFs })
100
+ await interceptedFs.writeFile(filePath, data)
101
+ })
102
+ })
@@ -0,0 +1,30 @@
1
+ import type { NodeishFilesystemSubset } from "@inlang/plugin"
2
+ import { normalizePath } from "@lix-js/fs"
3
+
4
+ export const createNodeishFsWithAbsolutePaths = (args: {
5
+ basePath: string
6
+ nodeishFs: NodeishFilesystemSubset
7
+ }): NodeishFilesystemSubset => {
8
+ const isAbsolutePath = (path: string) => /^[/\\]/.test(path)
9
+
10
+ if (!isAbsolutePath(args.basePath)) {
11
+ throw new Error("The argument `settingsFilePath` of `loadProject()` must be an absolute path.")
12
+ }
13
+
14
+ const intercept = (path: string) => {
15
+ if (isAbsolutePath(path)) {
16
+ return path
17
+ }
18
+
19
+ return normalizePath(args.basePath + "/" + path)
20
+ }
21
+
22
+ return {
23
+ // @ts-expect-error
24
+ readFile: (path: string, options: { encoding: "utf-8" | "binary" }) =>
25
+ args.nodeishFs.readFile(intercept(path), options),
26
+ readdir: (path: string) => args.nodeishFs.readdir(intercept(path)),
27
+ mkdir: (path: string) => args.nodeishFs.mkdir(intercept(path)),
28
+ writeFile: (path: string, data: string) => args.nodeishFs.writeFile(intercept(path), data),
29
+ }
30
+ }
@@ -1,12 +1,13 @@
1
+ import type { ValueError } from "@sinclair/typebox/errors"
1
2
  export * from "./plugins/errors.js"
2
3
  export * from "./message-lint-rules/errors.js"
3
4
 
4
5
  export class ModuleError extends Error {
5
- public readonly Module: string
6
+ public readonly module: string
6
7
  constructor(message: string, options: { module: string; cause?: Error }) {
7
8
  super(message)
8
9
  this.name = "ModuleError"
9
- this.Module = options.module
10
+ this.module = options.module
10
11
  this.cause = options.cause
11
12
  }
12
13
  }
@@ -15,8 +16,8 @@ export class ModuleError extends Error {
15
16
  * Error when a Module does not export any plugins or lint rules.
16
17
  */
17
18
  export class ModuleHasNoExportsError extends ModuleError {
18
- constructor(message: string, options: { module: string; cause?: Error }) {
19
- super(message, options)
19
+ constructor(options: { module: string; cause?: Error }) {
20
+ super(`Module "${module}" has no exports. Every module must have an "export default".`, options)
20
21
  this.name = "ModuleHasNoExportsError"
21
22
  }
22
23
  }
@@ -25,15 +26,20 @@ export class ModuleHasNoExportsError extends ModuleError {
25
26
  * Error when a Module cannot be imported.
26
27
  */
27
28
  export class ModuleImportError extends ModuleError {
28
- constructor(message: string, options: { module: string; cause: Error }) {
29
- super(message, options)
29
+ constructor(options: { module: string; cause: Error }) {
30
+ super(`Couldn't import the plugin "${module}":\n\n${options.cause}`, options)
30
31
  this.name = "ModuleImportError"
31
32
  }
32
33
  }
33
34
 
34
35
  export class ModuleExportIsInvalidError extends ModuleError {
35
- constructor(message: string, options: { module: string; cause?: Error }) {
36
- super(message, options)
36
+ constructor(options: { module: string; errors: ValueError[] }) {
37
+ super(
38
+ `The export(s) of "${module}" are invalid:\n\n${options.errors
39
+ .map((error) => `Path "${error.path}" with value "${error.value}": "${error.message}"`)
40
+ .join("\n")}`,
41
+ options
42
+ )
37
43
  this.name = "ModuleExportIsInvalidError"
38
44
  }
39
45
  }
@@ -1,5 +1,4 @@
1
1
  import dedent from "dedent"
2
- import { normalizePath } from "@lix-js/fs"
3
2
  import type { NodeishFilesystemSubset } from "@inlang/plugin"
4
3
  import { ModuleImportError } from "./errors.js"
5
4
 
@@ -42,7 +41,9 @@ async function $import(
42
41
  if (uri.startsWith("http")) {
43
42
  moduleAsText = await (await fetch(uri)).text()
44
43
  } else {
45
- moduleAsText = await options.readFile(normalizePath(uri), { encoding: "utf-8" })
44
+ moduleAsText = await options.readFile(uri, {
45
+ encoding: "utf-8",
46
+ })
46
47
  }
47
48
 
48
49
  const moduleWithMimeType = "data:application/javascript," + encodeURIComponent(moduleAsText)
@@ -50,14 +51,13 @@ async function $import(
50
51
  try {
51
52
  return await import(/* @vite-ignore */ moduleWithMimeType)
52
53
  } catch (error) {
53
- let message = `Error while importing ${uri}: ${(error as Error)?.message ?? "Unknown error"}`
54
54
  if (error instanceof SyntaxError && uri.includes("jsdelivr")) {
55
- message += dedent`\n\n
55
+ error.message += dedent`\n\n
56
56
  Are you sure that the file exists on JSDelivr?
57
57
 
58
58
  The error indicates that the imported file does not exist on JSDelivr. For non-existent files, JSDelivr returns a 404 text that JS cannot parse as a module and throws a SyntaxError.
59
59
  `
60
60
  }
61
- throw new ModuleImportError(message, { module: uri, cause: error as Error })
61
+ throw new ModuleImportError({ module: uri, cause: error as Error })
62
62
  }
63
63
  }
@@ -1,9 +1,9 @@
1
- export class MessageLintRuleIsInvalidError extends Error {
2
- public readonly module: string
1
+ import type { MessageLintRule } from "@inlang/message-lint-rule"
2
+ import type { ValueError } from "@sinclair/typebox/errors"
3
3
 
4
- constructor(message: string, options: { module: string; cause?: Error }) {
5
- super(message)
6
- this.module = options.module
4
+ export class MessageLintRuleIsInvalidError extends Error {
5
+ constructor(options: { id: MessageLintRule["id"]; errors: ValueError[] }) {
6
+ super(`The message lint rule "${options.id}" is invalid:\n\n${options.errors.join("\n")}`)
7
7
  this.name = "MessageLintRuleIsInvalidError"
8
8
  }
9
9
  }
@@ -9,9 +9,11 @@ export const resolveMessageLintRules = (args: { messageLintRules: Array<MessageL
9
9
  }
10
10
  for (const rule of args.messageLintRules) {
11
11
  if (Value.Check(MessageLintRule, rule) === false) {
12
+ const errors = [...Value.Errors(MessageLintRule, rule)]
12
13
  result.errors.push(
13
- new MessageLintRuleIsInvalidError(`Couldn't parse lint rule "${rule.id}"`, {
14
- module: "not implemented",
14
+ new MessageLintRuleIsInvalidError({
15
+ id: rule.id,
16
+ errors,
15
17
  })
16
18
  )
17
19
  continue
@@ -1,65 +1,63 @@
1
1
  import type { Plugin } from "@inlang/plugin"
2
+ import type { ValueError } from "@sinclair/typebox/errors"
2
3
 
3
- type PluginErrorOptions = {
4
- plugin: Plugin["id"] | undefined
5
- } & Partial<Error>
6
-
7
- class PluginError extends Error {
8
- public readonly plugin: string
9
-
10
- constructor(message: string, options: PluginErrorOptions) {
11
- super(message)
12
- this.name = "PluginError"
13
- this.plugin = options.plugin ?? "unknown"
14
- }
15
- }
16
-
17
- export class PluginHasInvalidIdError extends PluginError {
18
- constructor(message: string, options: PluginErrorOptions) {
19
- super(message, options)
4
+ export class PluginHasInvalidIdError extends Error {
5
+ constructor(options: { id: Plugin["id"] }) {
6
+ super(
7
+ `Plugin "${options.id}" has an invalid id. The id must:\n1) Start with "plugin."\n2) camelCase\n3) Contain a namespace.\nAn example would be "plugin.namespace.myPlugin".`
8
+ )
20
9
  this.name = "PluginHasInvalidIdError"
21
10
  }
22
11
  }
23
12
 
24
- export class PluginUsesReservedNamespaceError extends PluginError {
25
- constructor(message: string, options: PluginErrorOptions) {
26
- super(message, options)
13
+ export class PluginUsesReservedNamespaceError extends Error {
14
+ constructor(options: { id: Plugin["id"] }) {
15
+ super(`Plugin ${options.id} uses reserved namespace 'inlang'.`)
27
16
  this.name = "PluginUsesReservedNamespaceError"
28
17
  }
29
18
  }
30
19
 
31
- export class PluginHasInvalidSchemaError extends PluginError {
32
- constructor(message: string, options: PluginErrorOptions) {
33
- super(message, options)
20
+ export class PluginHasInvalidSchemaError extends Error {
21
+ constructor(options: { id: Plugin["id"]; errors: ValueError[] }) {
22
+ super(
23
+ `Plugin "${options.id}" has an invalid schema:\n\n${options.errors
24
+ .map((error) => `Path "${error.path}" with value "${error.value}": "${error.message}"`)
25
+ .join("\n")})}\n\nPlease refer to the documentation for the correct schema.`
26
+ )
34
27
  this.name = "PluginHasInvalidSchemaError"
35
28
  }
36
29
  }
37
30
 
38
- export class PluginLoadMessagesFunctionAlreadyDefinedError extends PluginError {
39
- constructor(message: string, options: PluginErrorOptions) {
40
- super(message, options)
31
+ export class PluginLoadMessagesFunctionAlreadyDefinedError extends Error {
32
+ constructor(options: { id: Plugin["id"] }) {
33
+ super(
34
+ `Plugin "${options.id}" defines the \`loadMessages()\` function, but it was already defined by another plugin.\n\nInlang only allows one plugin to define the \`loadMessages()\` function.`
35
+ )
41
36
  this.name = "PluginLoadMessagesFunctionAlreadyDefinedError"
42
37
  }
43
38
  }
44
39
 
45
- export class PluginSaveMessagesFunctionAlreadyDefinedError extends PluginError {
46
- constructor(message: string, options: PluginErrorOptions) {
47
- super(message, options)
40
+ export class PluginSaveMessagesFunctionAlreadyDefinedError extends Error {
41
+ constructor(options: { id: Plugin["id"] }) {
42
+ super(
43
+ `Plugin "${options.id}" defines the \`saveMessages()\` function, but it was already defined by another plugin.\n\nInlang only allows one plugin to define the \`saveMessages()\` function.`
44
+ )
48
45
  this.name = "PluginSaveMessagesFunctionAlreadyDefinedError"
49
46
  }
50
47
  }
51
48
 
52
- export class PluginReturnedInvalidCustomApiError extends PluginError {
53
- constructor(message: string, options: PluginErrorOptions) {
54
- super(message, options)
49
+ export class PluginReturnedInvalidCustomApiError extends Error {
50
+ constructor(options: { id: Plugin["id"]; cause: ErrorOptions["cause"] }) {
51
+ super(`Plugin "${options.id}" returned an invalid custom API:\n\n${options.cause}`, options)
55
52
  this.name = "PluginReturnedInvalidCustomApiError"
56
53
  }
57
54
  }
58
55
 
59
- export class PluginsDoNotProvideLoadOrSaveMessagesError extends PluginError {
60
- constructor(message: string, options: PluginErrorOptions) {
61
- super(message, options)
56
+ export class PluginsDoNotProvideLoadOrSaveMessagesError extends Error {
57
+ constructor() {
58
+ super(
59
+ `No plugin provides a \`loadMessages()\` or \`saveMessages()\` function\n\nIn case no plugin threw an error, you likely forgot to add a plugin that handles the loading and saving of messages. Refer to the marketplace for available plugins https://inlang.com/marketplace.`
60
+ )
62
61
  this.name = "PluginsDoNotProvideLoadOrSaveMessagesError"
63
- options.plugin = "plugin.inlang.missing"
64
62
  }
65
63
  }
@@ -42,56 +42,35 @@ export const resolvePlugins: ResolvePluginsFunction = async (args) => {
42
42
  // -- INVALID ID in META --
43
43
  const hasInvalidId = errors.some((error) => error.path === "/id")
44
44
  if (hasInvalidId) {
45
- result.errors.push(
46
- new PluginHasInvalidIdError(
47
- `Plugin ${plugin.id} has an invalid id "${plugin.id}". It must be camelCase and contain a namespace like plugin.namespace.myPlugin.`,
48
- { plugin: plugin.id }
49
- )
50
- )
45
+ result.errors.push(new PluginHasInvalidIdError({ id: plugin.id }))
51
46
  }
52
47
 
53
48
  // -- USES RESERVED NAMESPACE --
54
49
  if (plugin.id.includes("inlang") && !whitelistedPlugins.includes(plugin.id)) {
55
50
  result.errors.push(
56
- new PluginUsesReservedNamespaceError(
57
- `Plugin ${plugin.id} uses reserved namespace 'inlang'.`,
58
- {
59
- plugin: plugin.id,
60
- }
61
- )
51
+ new PluginUsesReservedNamespaceError({
52
+ id: plugin.id,
53
+ })
62
54
  )
63
55
  }
64
56
 
65
57
  // -- USES INVALID SCHEMA --
66
58
  if (errors.length > 0) {
67
59
  result.errors.push(
68
- new PluginHasInvalidSchemaError(
69
- `Plugin ${plugin.id} uses an invalid schema. Please check the documentation for the correct Plugin type.`,
70
- {
71
- plugin: plugin.id,
72
- cause: errors,
73
- }
74
- )
60
+ new PluginHasInvalidSchemaError({
61
+ id: plugin.id,
62
+ errors: errors,
63
+ })
75
64
  )
76
65
  }
77
66
 
78
67
  // -- ALREADY DEFINED LOADMESSAGES / SAVEMESSAGES / DETECTEDLANGUAGETAGS --
79
68
  if (typeof plugin.loadMessages === "function" && result.data.loadMessages !== undefined) {
80
- result.errors.push(
81
- new PluginLoadMessagesFunctionAlreadyDefinedError(
82
- `Plugin ${plugin.id} defines the loadMessages function, but it was already defined by another plugin.`,
83
- { plugin: plugin.id }
84
- )
85
- )
69
+ result.errors.push(new PluginLoadMessagesFunctionAlreadyDefinedError({ id: plugin.id }))
86
70
  }
87
71
 
88
72
  if (typeof plugin.saveMessages === "function" && result.data.saveMessages !== undefined) {
89
- result.errors.push(
90
- new PluginSaveMessagesFunctionAlreadyDefinedError(
91
- `Plugin ${plugin.id} defines the saveMessages function, but it was already defined by another plugin.`,
92
- { plugin: plugin.id }
93
- )
94
- )
73
+ result.errors.push(new PluginSaveMessagesFunctionAlreadyDefinedError({ id: plugin.id }))
95
74
  }
96
75
 
97
76
  // --- ADD APP SPECIFIC API ---
@@ -103,16 +82,13 @@ export const resolvePlugins: ResolvePluginsFunction = async (args) => {
103
82
  })
104
83
  )
105
84
  if (error) {
106
- // @ts-ignore
107
- delete error.stack
108
- result.errors.push(error as any) // TODO: add correct error type
109
- }
110
- if (typeof customApi !== "object") {
85
+ result.errors.push(new PluginReturnedInvalidCustomApiError({ id: plugin.id, cause: error }))
86
+ } else if (typeof customApi !== "object") {
111
87
  result.errors.push(
112
- new PluginReturnedInvalidCustomApiError(
113
- `Plugin ${plugin.id} defines the addCustomApi function, but it does not return an object.`,
114
- { plugin: plugin.id, cause: error }
115
- )
88
+ new PluginReturnedInvalidCustomApiError({
89
+ id: plugin.id,
90
+ cause: new Error(`The return value must be an object. Received "${typeof customApi}".`),
91
+ })
116
92
  )
117
93
  }
118
94
  }
@@ -159,12 +135,7 @@ export const resolvePlugins: ResolvePluginsFunction = async (args) => {
159
135
  typeof result.data.loadMessages !== "function" ||
160
136
  typeof result.data.saveMessages !== "function"
161
137
  ) {
162
- result.errors.push(
163
- new PluginsDoNotProvideLoadOrSaveMessagesError(
164
- "It seems you did not install any plugin that handles messages. Please add one to make inlang work. See https://inlang.com/documentation/plugins/registry.",
165
- { plugin: undefined }
166
- )
167
- )
138
+ result.errors.push(new PluginsDoNotProvideLoadOrSaveMessagesError())
168
139
  }
169
140
 
170
141
  return result
@@ -1,4 +1,4 @@
1
- import type { NodeishFilesystem as LisaNodeishFilesystem } from "@lix-js/fs"
1
+ import type { NodeishFilesystem } from "@lix-js/fs"
2
2
  import type {
3
3
  PluginReturnedInvalidCustomApiError,
4
4
  PluginLoadMessagesFunctionAlreadyDefinedError,
@@ -18,7 +18,7 @@ import type { ProjectSettings } from "@inlang/project-settings"
18
18
  * - only uses minimally required functions to decrease the API footprint on the ecosystem.
19
19
  */
20
20
  export type NodeishFilesystemSubset = Pick<
21
- LisaNodeishFilesystem,
21
+ NodeishFilesystem,
22
22
  "readFile" | "readdir" | "mkdir" | "writeFile"
23
23
  >
24
24
 
@@ -23,7 +23,7 @@ it("should return an error if a plugin cannot be imported", async () => {
23
23
  settings,
24
24
  nodeishFs: {} as any,
25
25
  _import: () => {
26
- throw new ModuleImportError("Could not import", {
26
+ throw new ModuleImportError({
27
27
  module: settings.modules[0]!,
28
28
  cause: new Error("Could not import"),
29
29
  })
@@ -94,7 +94,7 @@ it("should return an error if a module cannot be imported", async () => {
94
94
  }
95
95
 
96
96
  const _import = async () => {
97
- throw new ModuleImportError("Could not import", {
97
+ throw new ModuleImportError({
98
98
  module: settings.modules[0]!,
99
99
  cause: new Error(),
100
100
  })
@@ -35,7 +35,7 @@ export const resolveModules: ResolveModuleFunction = async (args) => {
35
35
  // -- IMPORT MODULE --
36
36
  if (importedModule.error) {
37
37
  moduleErrors.push(
38
- new ModuleImportError(`Couldn't import the plugin "${module}"`, {
38
+ new ModuleImportError({
39
39
  module: module,
40
40
  cause: importedModule.error as Error,
41
41
  })
@@ -46,7 +46,7 @@ export const resolveModules: ResolveModuleFunction = async (args) => {
46
46
  // -- MODULE DOES NOT EXPORT ANYTHING --
47
47
  if (importedModule.data?.default === undefined) {
48
48
  moduleErrors.push(
49
- new ModuleHasNoExportsError(`Module "${module}" has no exports.`, {
49
+ new ModuleHasNoExportsError({
50
50
  module: module,
51
51
  })
52
52
  )
@@ -56,12 +56,11 @@ export const resolveModules: ResolveModuleFunction = async (args) => {
56
56
  const isValidModule = ModuleCompiler.Check(importedModule.data)
57
57
 
58
58
  if (isValidModule === false) {
59
- const errors = [...ModuleCompiler.Errors(importedModule.data)].map(
60
- (e) => `${e.path} ${e.message}`
61
- )
59
+ const errors = [...ModuleCompiler.Errors(importedModule.data)]
62
60
  moduleErrors.push(
63
- new ModuleExportIsInvalidError(`Module "${module}" is invalid: ` + errors.join("\n"), {
61
+ new ModuleExportIsInvalidError({
64
62
  module: module,
63
+ errors,
65
64
  })
66
65
  )
67
66
  continue