@inlang/sdk 0.2.0 → 0.3.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 (38) hide show
  1. package/dist/errors.d.ts +0 -6
  2. package/dist/errors.d.ts.map +1 -1
  3. package/dist/errors.js +0 -9
  4. package/dist/index.d.ts +1 -1
  5. package/dist/index.d.ts.map +1 -1
  6. package/dist/index.js +1 -1
  7. package/dist/openInlangProject.d.ts.map +1 -1
  8. package/dist/openInlangProject.js +1 -6
  9. package/dist/openInlangProject.test.js +2 -28
  10. package/dist/resolve-modules/import.d.ts +0 -6
  11. package/dist/resolve-modules/import.d.ts.map +1 -1
  12. package/dist/resolve-modules/import.js +1 -1
  13. package/dist/resolve-modules/import.test.js +0 -1
  14. package/dist/resolve-modules/plugins/errors.d.ts +3 -0
  15. package/dist/resolve-modules/plugins/errors.d.ts.map +1 -1
  16. package/dist/resolve-modules/plugins/errors.js +7 -0
  17. package/dist/resolve-modules/plugins/resolvePlugins.d.ts.map +1 -1
  18. package/dist/resolve-modules/plugins/resolvePlugins.js +6 -1
  19. package/dist/resolve-modules/plugins/resolvePlugins.test.js +36 -6
  20. package/dist/resolve-modules/plugins/types.d.ts +2 -2
  21. package/dist/resolve-modules/plugins/types.d.ts.map +1 -1
  22. package/dist/resolve-modules/resolveModules.js +1 -1
  23. package/dist/test-utilities/index.d.ts +1 -0
  24. package/dist/test-utilities/index.d.ts.map +1 -1
  25. package/dist/test-utilities/index.js +1 -0
  26. package/package.json +1 -1
  27. package/src/errors.ts +0 -12
  28. package/src/index.ts +0 -1
  29. package/src/openInlangProject.test.ts +1 -36
  30. package/src/openInlangProject.ts +0 -8
  31. package/src/resolve-modules/import.test.ts +0 -1
  32. package/src/resolve-modules/import.ts +1 -7
  33. package/src/resolve-modules/plugins/errors.ts +8 -0
  34. package/src/resolve-modules/plugins/resolvePlugins.test.ts +41 -5
  35. package/src/resolve-modules/plugins/resolvePlugins.ts +14 -0
  36. package/src/resolve-modules/plugins/types.ts +2 -0
  37. package/src/resolve-modules/resolveModules.ts +2 -2
  38. package/src/test-utilities/index.ts +1 -0
package/dist/errors.d.ts CHANGED
@@ -13,10 +13,4 @@ export declare class PluginSaveMessagesError extends Error {
13
13
  export declare class PluginLoadMessagesError extends Error {
14
14
  constructor(message: string, options: ErrorOptions);
15
15
  }
16
- /**
17
- * Error when no package provides the API to handle messages.
18
- */
19
- export declare class NoPluginProvidesLoadOrSaveMessagesError extends Error {
20
- constructor();
21
- }
22
16
  //# sourceMappingURL=errors.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,qBAAa,kBAAmB,SAAQ,KAAK;gBAChC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY;CAIlD;AAED,qBAAa,0BAA2B,SAAQ,KAAK;gBACxC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY;CAIlD;AAED,qBAAa,4BAA6B,SAAQ,KAAK;gBAC1C,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY;CAIlD;AAED,qBAAa,uBAAwB,SAAQ,KAAK;gBACrC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY;CAIlD;AAED,qBAAa,uBAAwB,SAAQ,KAAK;gBACrC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY;CAIlD;AAED;;GAEG;AACH,qBAAa,uCAAwC,SAAQ,KAAK;;CAOjE"}
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,qBAAa,kBAAmB,SAAQ,KAAK;gBAChC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY;CAIlD;AAED,qBAAa,0BAA2B,SAAQ,KAAK;gBACxC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY;CAIlD;AAED,qBAAa,4BAA6B,SAAQ,KAAK;gBAC1C,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY;CAIlD;AAED,qBAAa,uBAAwB,SAAQ,KAAK;gBACrC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY;CAIlD;AAED,qBAAa,uBAAwB,SAAQ,KAAK;gBACrC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY;CAIlD"}
package/dist/errors.js CHANGED
@@ -28,12 +28,3 @@ export class PluginLoadMessagesError extends Error {
28
28
  this.name = "PluginLoadMessagesError";
29
29
  }
30
30
  }
31
- /**
32
- * Error when no package provides the API to handle messages.
33
- */
34
- export class NoPluginProvidesLoadOrSaveMessagesError extends Error {
35
- constructor() {
36
- super("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."); // TODO: check if link is correct
37
- this.name = "NoPluginProvidesLoadOrSaveMessagesError";
38
- }
39
- }
package/dist/index.d.ts CHANGED
@@ -8,7 +8,7 @@ export { type ImportFunction, createImport } from "./resolve-modules/index.js";
8
8
  export { openInlangProject } from "./openInlangProject.js";
9
9
  export { solidAdapter, type InlangProjectWithSolidAdapter } from "./adapter/solidAdapter.js";
10
10
  export { createMessagesQuery } from "./createMessagesQuery.js";
11
- export { ProjectFilePathNotFoundError, ProjectFileJSONSyntaxError, InvalidConfigError, NoPluginProvidesLoadOrSaveMessagesError, PluginLoadMessagesError, PluginSaveMessagesError, } from "./errors.js";
11
+ export { ProjectFilePathNotFoundError, ProjectFileJSONSyntaxError, InvalidConfigError, PluginLoadMessagesError, PluginSaveMessagesError, } from "./errors.js";
12
12
  export * from "./messages/variant.js";
13
13
  export * from "./versionedInterfaces.js";
14
14
  export { InlangModule } from "@inlang/module";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,YAAY,EACX,aAAa,EACb,wBAAwB,EACxB,eAAe,EACf,eAAe,EACf,YAAY,GACZ,MAAM,UAAU,CAAA;AACjB,OAAO,EAAE,KAAK,cAAc,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAA;AAC9E,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAA;AAC1D,OAAO,EAAE,YAAY,EAAE,KAAK,6BAA6B,EAAE,MAAM,2BAA2B,CAAA;AAC5F,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAA;AAC9D,OAAO,EACN,4BAA4B,EAC5B,0BAA0B,EAC1B,kBAAkB,EAClB,uCAAuC,EACvC,uBAAuB,EACvB,uBAAuB,GACvB,MAAM,aAAa,CAAA;AAEpB,cAAc,uBAAuB,CAAA;AACrC,cAAc,0BAA0B,CAAA;AACxC,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,YAAY,EACX,aAAa,EACb,wBAAwB,EACxB,eAAe,EACf,eAAe,EACf,YAAY,GACZ,MAAM,UAAU,CAAA;AACjB,OAAO,EAAE,KAAK,cAAc,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAA;AAC9E,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAA;AAC1D,OAAO,EAAE,YAAY,EAAE,KAAK,6BAA6B,EAAE,MAAM,2BAA2B,CAAA;AAC5F,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAA;AAC9D,OAAO,EACN,4BAA4B,EAC5B,0BAA0B,EAC1B,kBAAkB,EAClB,uBAAuB,EACvB,uBAAuB,GACvB,MAAM,aAAa,CAAA;AAEpB,cAAc,uBAAuB,CAAA;AACrC,cAAc,0BAA0B,CAAA;AACxC,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA"}
package/dist/index.js CHANGED
@@ -7,7 +7,7 @@ export { createImport } from "./resolve-modules/index.js";
7
7
  export { openInlangProject } from "./openInlangProject.js";
8
8
  export { solidAdapter } from "./adapter/solidAdapter.js";
9
9
  export { createMessagesQuery } from "./createMessagesQuery.js";
10
- export { ProjectFilePathNotFoundError, ProjectFileJSONSyntaxError, InvalidConfigError, NoPluginProvidesLoadOrSaveMessagesError, PluginLoadMessagesError, PluginSaveMessagesError, } from "./errors.js";
10
+ export { ProjectFilePathNotFoundError, ProjectFileJSONSyntaxError, InvalidConfigError, PluginLoadMessagesError, PluginSaveMessagesError, } from "./errors.js";
11
11
  export * from "./messages/variant.js";
12
12
  export * from "./versionedInterfaces.js";
13
13
  export { InlangModule } from "@inlang/module";
@@ -1 +1 @@
1
- {"version":3,"file":"openInlangProject.d.ts","sourceRoot":"","sources":["../src/openInlangProject.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACX,aAAa,EAGb,YAAY,EACZ,MAAM,UAAU,CAAA;AACjB,OAAO,EAAE,KAAK,cAAc,EAAkB,MAAM,4BAA4B,CAAA;AAehF,OAAO,EAA0B,KAAK,uBAAuB,EAAE,MAAM,0BAA0B,CAAA;AAK/F;;;;;;GAMG;AACH,eAAO,MAAM,iBAAiB;qBACZ,MAAM;eACZ,uBAAuB;;qBAElB,MAAM,SAAS,OAAO,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI;MAC5D,QAAQ,aAAa,CAwLxB,CAAA;AAyGD,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,YAAY,CAAC,CAAC,CAAC,CAQtE"}
1
+ {"version":3,"file":"openInlangProject.d.ts","sourceRoot":"","sources":["../src/openInlangProject.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACX,aAAa,EAGb,YAAY,EACZ,MAAM,UAAU,CAAA;AACjB,OAAO,EAAE,KAAK,cAAc,EAAkB,MAAM,4BAA4B,CAAA;AAchF,OAAO,EAA0B,KAAK,uBAAuB,EAAE,MAAM,0BAA0B,CAAA;AAK/F;;;;;;GAMG;AACH,eAAO,MAAM,iBAAiB;qBACZ,MAAM;eACZ,uBAAuB;;qBAElB,MAAM,SAAS,OAAO,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI;MAC5D,QAAQ,aAAa,CAiLxB,CAAA;AAyGD,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,YAAY,CAAC,CAAC,CAAC,CAQtE"}
@@ -1,7 +1,7 @@
1
1
  import { resolveModules } from "./resolve-modules/index.js";
2
2
  import { TypeCompiler } from "@sinclair/typebox/compiler";
3
3
  import { Value } from "@sinclair/typebox/value";
4
- import { ProjectFilePathNotFoundError, ProjectFileJSONSyntaxError, InvalidConfigError, NoPluginProvidesLoadOrSaveMessagesError, PluginLoadMessagesError, PluginSaveMessagesError, } from "./errors.js";
4
+ import { ProjectFilePathNotFoundError, ProjectFileJSONSyntaxError, InvalidConfigError, PluginLoadMessagesError, PluginSaveMessagesError, } from "./errors.js";
5
5
  import { createRoot, createSignal, createEffect } from "./reactivity/solid.js";
6
6
  import { createMessagesQuery } from "./createMessagesQuery.js";
7
7
  import { debounce } from "throttle-debounce";
@@ -55,11 +55,6 @@ export const openInlangProject = async (args) => {
55
55
  return;
56
56
  loadModules({ config: conf, nodeishFs: args.nodeishFs, _import: args._import })
57
57
  .then((resolvedModules) => {
58
- // TODO move to resolveModules
59
- if (!resolvedModules.resolvedPluginApi.loadMessages ||
60
- !resolvedModules.resolvedPluginApi.saveMessages) {
61
- throw new NoPluginProvidesLoadOrSaveMessagesError();
62
- }
63
58
  setResolvedModules(resolvedModules);
64
59
  // TODO: handle `detectedLanguageTags`
65
60
  })
@@ -1,7 +1,7 @@
1
1
  /* eslint-disable @typescript-eslint/no-non-null-assertion */
2
2
  import { describe, it, expect, vi } from "vitest";
3
3
  import { openInlangProject } from "./openInlangProject.js";
4
- import { ProjectFilePathNotFoundError, ProjectFileJSONSyntaxError, InvalidConfigError, NoPluginProvidesLoadOrSaveMessagesError, } from "./errors.js";
4
+ import { ProjectFilePathNotFoundError, ProjectFileJSONSyntaxError, InvalidConfigError, } from "./errors.js";
5
5
  import { createNodeishMemoryFs } from "@lix-js/fs";
6
6
  // ------------------------------------------------------------------------------------------------
7
7
  const getValue = (subscribable) => {
@@ -144,32 +144,6 @@ describe("initialization", () => {
144
144
  });
145
145
  });
146
146
  describe("modules", () => {
147
- it("should return an error if no plugin defines readMessages", async () => {
148
- const $badImport = async () => ({
149
- default: { ...mockPlugin, loadMessages: undefined },
150
- });
151
- const fs = await createNodeishMemoryFs();
152
- await fs.writeFile("./project.inlang.json", JSON.stringify(config));
153
- const inlang = await openInlangProject({
154
- projectFilePath: "./project.inlang.json",
155
- nodeishFs: fs,
156
- _import: $badImport,
157
- });
158
- expect(inlang.errors()[0]).toBeInstanceOf(NoPluginProvidesLoadOrSaveMessagesError);
159
- });
160
- it("should return an error if no plugin defines writeMessages", async () => {
161
- const $badImport = async () => ({
162
- default: { ...mockPlugin, writeMessages: undefined },
163
- });
164
- const fs = createNodeishMemoryFs();
165
- await fs.writeFile("./project.inlang.json", JSON.stringify(config));
166
- const inlang = await openInlangProject({
167
- projectFilePath: "./project.inlang.json",
168
- nodeishFs: fs,
169
- _import: $badImport,
170
- });
171
- expect(inlang.errors()[0]).toBeInstanceOf(NoPluginProvidesLoadOrSaveMessagesError);
172
- });
173
147
  it("should return an error if an error occurs while resolving a plugin", async () => {
174
148
  const $badImport = async () => ({
175
149
  default: {},
@@ -181,7 +155,7 @@ describe("initialization", () => {
181
155
  nodeishFs: fs,
182
156
  _import: $badImport,
183
157
  });
184
- expect(inlang.errors()).toHaveLength(1);
158
+ expect(inlang.errors()).not.toHaveLength(0);
185
159
  });
186
160
  // it.todo("should throw if lintRules contain errors ???")
187
161
  // it.todo("should return meta data")
@@ -18,18 +18,12 @@ export type ImportFunction = (uri: string) => Promise<any>;
18
18
  export declare function createImport(args: {
19
19
  /** the fs from which the file can be read */
20
20
  readFile: NodeishFilesystemSubset["readFile"];
21
- /** http client implementation */
22
- fetch: typeof fetch;
23
21
  }): (uri: string) => ReturnType<typeof $import>;
24
22
  declare function $import(uri: string, options: {
25
23
  /**
26
24
  * Required to import from a local path.
27
25
  */
28
26
  readFile: NodeishFilesystemSubset["readFile"];
29
- /**
30
- * Required to import via network.
31
- */
32
- fetch: typeof fetch;
33
27
  }): Promise<any>;
34
28
  export {};
35
29
  //# sourceMappingURL=import.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"import.d.ts","sourceRoot":"","sources":["../../src/resolve-modules/import.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAA;AAG7D;;;;;GAKG;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,GAAG,CAAC,CAAA;AAE1D;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE;IAClC,6CAA6C;IAC7C,QAAQ,EAAE,uBAAuB,CAAC,UAAU,CAAC,CAAA;IAC7C,iCAAiC;IACjC,KAAK,EAAE,OAAO,KAAK,CAAA;CACnB,GAAG,CAAC,GAAG,EAAE,MAAM,KAAK,UAAU,CAAC,OAAO,OAAO,CAAC,CAG9C;AAED,iBAAe,OAAO,CACrB,GAAG,EAAE,MAAM,EACX,OAAO,EAAE;IACR;;OAEG;IACH,QAAQ,EAAE,uBAAuB,CAAC,UAAU,CAAC,CAAA;IAC7C;;OAEG;IACH,KAAK,EAAE,OAAO,KAAK,CAAA;CACnB,GACC,OAAO,CAAC,GAAG,CAAC,CAwBd"}
1
+ {"version":3,"file":"import.d.ts","sourceRoot":"","sources":["../../src/resolve-modules/import.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAA;AAG7D;;;;;GAKG;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,GAAG,CAAC,CAAA;AAE1D;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE;IAClC,6CAA6C;IAC7C,QAAQ,EAAE,uBAAuB,CAAC,UAAU,CAAC,CAAA;CAC7C,GAAG,CAAC,GAAG,EAAE,MAAM,KAAK,UAAU,CAAC,OAAO,OAAO,CAAC,CAG9C;AAED,iBAAe,OAAO,CACrB,GAAG,EAAE,MAAM,EACX,OAAO,EAAE;IACR;;OAEG;IACH,QAAQ,EAAE,uBAAuB,CAAC,UAAU,CAAC,CAAA;CAC7C,GACC,OAAO,CAAC,GAAG,CAAC,CAwBd"}
@@ -17,7 +17,7 @@ export function createImport(args) {
17
17
  async function $import(uri, options) {
18
18
  let moduleAsText;
19
19
  if (uri.startsWith("http")) {
20
- moduleAsText = await (await options.fetch(uri)).text();
20
+ moduleAsText = await (await fetch(uri)).text();
21
21
  }
22
22
  else {
23
23
  moduleAsText = await options.readFile(normalizePath(uri), { encoding: "utf-8" });
@@ -18,7 +18,6 @@ describe("$import", async () => {
18
18
  `);
19
19
  const _import = createImport({
20
20
  readFile: fs.readFile,
21
- fetch,
22
21
  });
23
22
  it("should import a module from a local path", async () => {
24
23
  const module = await _import("./mock-module.js");
@@ -24,5 +24,8 @@ export declare class PluginSaveMessagesFunctionAlreadyDefinedError extends Plugi
24
24
  export declare class PluginReturnedInvalidCustomApiError extends PluginError {
25
25
  constructor(message: string, options: PluginErrorOptions);
26
26
  }
27
+ export declare class PluginsDoNotProvideLoadOrSaveMessagesError extends PluginError {
28
+ constructor(message: string, options: PluginErrorOptions);
29
+ }
27
30
  export {};
28
31
  //# sourceMappingURL=errors.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../../src/resolve-modules/plugins/errors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAA;AAE5C,KAAK,kBAAkB,GAAG;IACzB,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAA;CAC5B,GAAG,OAAO,CAAC,KAAK,CAAC,CAAA;AAElB,cAAM,WAAY,SAAQ,KAAK;IAC9B,SAAgB,MAAM,EAAE,MAAM,CAAA;gBAElB,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,kBAAkB;CAKxD;AAED,qBAAa,uBAAwB,SAAQ,WAAW;gBAC3C,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,kBAAkB;CAIxD;AAED,qBAAa,gCAAiC,SAAQ,WAAW;gBACpD,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,kBAAkB;CAIxD;AAED,qBAAa,2BAA4B,SAAQ,WAAW;gBAC/C,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,kBAAkB;CAIxD;AAED,qBAAa,6CAA8C,SAAQ,WAAW;gBACjE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,kBAAkB;CAIxD;AAED,qBAAa,6CAA8C,SAAQ,WAAW;gBACjE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,kBAAkB;CAIxD;AAED,qBAAa,mCAAoC,SAAQ,WAAW;gBACvD,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,kBAAkB;CAIxD"}
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../../src/resolve-modules/plugins/errors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAA;AAE5C,KAAK,kBAAkB,GAAG;IACzB,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAA;CAC5B,GAAG,OAAO,CAAC,KAAK,CAAC,CAAA;AAElB,cAAM,WAAY,SAAQ,KAAK;IAC9B,SAAgB,MAAM,EAAE,MAAM,CAAA;gBAElB,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,kBAAkB;CAKxD;AAED,qBAAa,uBAAwB,SAAQ,WAAW;gBAC3C,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,kBAAkB;CAIxD;AAED,qBAAa,gCAAiC,SAAQ,WAAW;gBACpD,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,kBAAkB;CAIxD;AAED,qBAAa,2BAA4B,SAAQ,WAAW;gBAC/C,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,kBAAkB;CAIxD;AAED,qBAAa,6CAA8C,SAAQ,WAAW;gBACjE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,kBAAkB;CAIxD;AAED,qBAAa,6CAA8C,SAAQ,WAAW;gBACjE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,kBAAkB;CAIxD;AAED,qBAAa,mCAAoC,SAAQ,WAAW;gBACvD,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,kBAAkB;CAIxD;AAED,qBAAa,0CAA2C,SAAQ,WAAW;gBAC9D,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,kBAAkB;CAKxD"}
@@ -42,3 +42,10 @@ export class PluginReturnedInvalidCustomApiError extends PluginError {
42
42
  this.name = "PluginReturnedInvalidCustomApiError";
43
43
  }
44
44
  }
45
+ export class PluginsDoNotProvideLoadOrSaveMessagesError extends PluginError {
46
+ constructor(message, options) {
47
+ super(message, options);
48
+ this.name = "PluginsDoNotProvideLoadOrSaveMessagesError";
49
+ options.plugin = "plugin.inlang.missing";
50
+ }
51
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"resolvePlugins.d.ts","sourceRoot":"","sources":["../../../src/resolve-modules/plugins/resolvePlugins.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAA;AAsBxD,eAAO,MAAM,cAAc,EAAE,sBAkJ5B,CAAA"}
1
+ {"version":3,"file":"resolvePlugins.d.ts","sourceRoot":"","sources":["../../../src/resolve-modules/plugins/resolvePlugins.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAA;AAuBxD,eAAO,MAAM,cAAc,EAAE,sBA+J5B,CAAA"}
@@ -1,5 +1,5 @@
1
1
  import { Plugin } from "@inlang/plugin";
2
- import { PluginReturnedInvalidCustomApiError, PluginLoadMessagesFunctionAlreadyDefinedError, PluginSaveMessagesFunctionAlreadyDefinedError, PluginHasInvalidIdError, PluginHasInvalidSchemaError, PluginUsesReservedNamespaceError, } from "./errors.js";
2
+ import { PluginReturnedInvalidCustomApiError, PluginLoadMessagesFunctionAlreadyDefinedError, PluginSaveMessagesFunctionAlreadyDefinedError, PluginsDoNotProvideLoadOrSaveMessagesError, PluginHasInvalidIdError, PluginHasInvalidSchemaError, PluginUsesReservedNamespaceError, } from "./errors.js";
3
3
  import { deepmerge } from "deepmerge-ts";
4
4
  import { TypeCompiler } from "@sinclair/typebox/compiler";
5
5
  import { tryCatch } from "@inlang/result";
@@ -104,5 +104,10 @@ export const resolvePlugins = async (args) => {
104
104
  }
105
105
  }
106
106
  }
107
+ // --- LOADMESSAGE / SAVEMESSAGE NOT DEFINED ---
108
+ if (typeof result.data.loadMessages !== "function" ||
109
+ typeof result.data.saveMessages !== "function") {
110
+ result.errors.push(new PluginsDoNotProvideLoadOrSaveMessagesError("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.", { plugin: "plugin.inlang.missing" }));
111
+ }
107
112
  return result;
108
113
  };
@@ -1,7 +1,7 @@
1
1
  /* eslint-disable @typescript-eslint/no-non-null-assertion */
2
2
  import { describe, expect, it } from "vitest";
3
3
  import { resolvePlugins } from "./resolvePlugins.js";
4
- import { PluginLoadMessagesFunctionAlreadyDefinedError, PluginSaveMessagesFunctionAlreadyDefinedError, PluginHasInvalidIdError, PluginUsesReservedNamespaceError, PluginReturnedInvalidCustomApiError, PluginHasInvalidSchemaError, } from "./errors.js";
4
+ import { PluginLoadMessagesFunctionAlreadyDefinedError, PluginSaveMessagesFunctionAlreadyDefinedError, PluginHasInvalidIdError, PluginUsesReservedNamespaceError, PluginReturnedInvalidCustomApiError, PluginHasInvalidSchemaError, PluginsDoNotProvideLoadOrSaveMessagesError, } from "./errors.js";
5
5
  describe("generally", () => {
6
6
  it("should return an error if a plugin uses an invalid id", async () => {
7
7
  const mockPlugin = {
@@ -43,7 +43,6 @@ describe("generally", () => {
43
43
  settings: {},
44
44
  nodeishFs: {},
45
45
  });
46
- expect(resolved.errors.length).toBe(1);
47
46
  expect(resolved.errors[0]).toBeInstanceOf(PluginHasInvalidSchemaError);
48
47
  });
49
48
  it("should not initialize a plugin that uses the 'inlang' namespace except for inlang whitelisted plugins", async () => {
@@ -60,7 +59,6 @@ describe("generally", () => {
60
59
  settings: {},
61
60
  nodeishFs: {},
62
61
  });
63
- expect(resolved.errors.length).toBe(1);
64
62
  expect(resolved.errors[0]).toBeInstanceOf(PluginUsesReservedNamespaceError);
65
63
  });
66
64
  });
@@ -106,9 +104,25 @@ describe("loadMessages", () => {
106
104
  nodeishFs: {},
107
105
  settings: {},
108
106
  });
109
- expect(resolved.errors).toHaveLength(1);
110
107
  expect(resolved.errors[0]).toBeInstanceOf(PluginLoadMessagesFunctionAlreadyDefinedError);
111
108
  });
109
+ it("should return an error if no plugin defines loadMessages", async () => {
110
+ const mockPlugin = {
111
+ meta: {
112
+ id: "plugin.namepsace.loadMessagesFirst",
113
+ description: { en: "My plugin description" },
114
+ displayName: { en: "My plugin" },
115
+ },
116
+ saveMessages: async () => undefined,
117
+ };
118
+ const resolved = await resolvePlugins({
119
+ plugins: [mockPlugin],
120
+ nodeishFs: {},
121
+ settings: {},
122
+ });
123
+ expect(resolved.errors).toHaveLength(1);
124
+ expect(resolved.errors[0]).toBeInstanceOf(PluginsDoNotProvideLoadOrSaveMessagesError);
125
+ });
112
126
  });
113
127
  describe("saveMessages", () => {
114
128
  it("should save messages to a local source", async () => {
@@ -118,6 +132,7 @@ describe("saveMessages", () => {
118
132
  description: { en: "My plugin description" },
119
133
  displayName: { en: "My plugin" },
120
134
  },
135
+ loadMessages: async () => undefined,
121
136
  saveMessages: async () => undefined,
122
137
  };
123
138
  const resolved = await resolvePlugins({
@@ -149,9 +164,25 @@ describe("saveMessages", () => {
149
164
  settings: {},
150
165
  nodeishFs: {},
151
166
  });
152
- expect(resolved.errors).toHaveLength(1);
153
167
  expect(resolved.errors[0]).toBeInstanceOf(PluginSaveMessagesFunctionAlreadyDefinedError);
154
168
  });
169
+ it("should return an error if no plugin defines saveMessages", async () => {
170
+ const mockPlugin = {
171
+ meta: {
172
+ id: "plugin.namepsace.loadMessagesFirst",
173
+ description: { en: "My plugin description" },
174
+ displayName: { en: "My plugin" },
175
+ },
176
+ loadMessages: async () => undefined,
177
+ };
178
+ const resolved = await resolvePlugins({
179
+ plugins: [mockPlugin],
180
+ nodeishFs: {},
181
+ settings: {},
182
+ });
183
+ expect(resolved.errors).toHaveLength(1);
184
+ expect(resolved.errors[0]).toBeInstanceOf(PluginsDoNotProvideLoadOrSaveMessagesError);
185
+ });
155
186
  });
156
187
  describe("detectedLanguageTags", () => {
157
188
  it("should merge language tags from plugins", async () => {
@@ -258,7 +289,6 @@ describe("addCustomApi", () => {
258
289
  settings: {},
259
290
  nodeishFs: {},
260
291
  });
261
- expect(resolved.errors).toHaveLength(1);
262
292
  expect(resolved.errors[0]).toBeInstanceOf(PluginReturnedInvalidCustomApiError);
263
293
  });
264
294
  it("it should throw an error if the passed options are not defined inside customApi", async () => {
@@ -1,6 +1,6 @@
1
1
  import type { LanguageTag } from "@inlang/language-tag";
2
2
  import type { NodeishFilesystem as LisaNodeishFilesystem } from "@lix-js/fs";
3
- import type { PluginReturnedInvalidCustomApiError, PluginLoadMessagesFunctionAlreadyDefinedError, PluginSaveMessagesFunctionAlreadyDefinedError, PluginHasInvalidIdError, PluginHasInvalidSchemaError, PluginUsesReservedNamespaceError } from "./errors.js";
3
+ import type { PluginReturnedInvalidCustomApiError, PluginLoadMessagesFunctionAlreadyDefinedError, PluginSaveMessagesFunctionAlreadyDefinedError, PluginHasInvalidIdError, PluginHasInvalidSchemaError, PluginUsesReservedNamespaceError, PluginsDoNotProvideLoadOrSaveMessagesError } from "./errors.js";
4
4
  import type { Message } from "@inlang/message";
5
5
  import type { JSONObject } from "@inlang/json-types";
6
6
  import type { CustomApiInlangIdeExtension, Plugin } from "@inlang/plugin";
@@ -19,7 +19,7 @@ export type ResolvePluginsFunction = (args: {
19
19
  nodeishFs: NodeishFilesystemSubset;
20
20
  }) => Promise<{
21
21
  data: ResolvedPluginApi;
22
- errors: Array<PluginReturnedInvalidCustomApiError | PluginLoadMessagesFunctionAlreadyDefinedError | PluginSaveMessagesFunctionAlreadyDefinedError | PluginHasInvalidIdError | PluginHasInvalidSchemaError | PluginUsesReservedNamespaceError>;
22
+ errors: Array<PluginReturnedInvalidCustomApiError | PluginLoadMessagesFunctionAlreadyDefinedError | PluginSaveMessagesFunctionAlreadyDefinedError | PluginHasInvalidIdError | PluginHasInvalidSchemaError | PluginUsesReservedNamespaceError | PluginsDoNotProvideLoadOrSaveMessagesError>;
23
23
  }>;
24
24
  /**
25
25
  * The API after resolving the plugins.
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/resolve-modules/plugins/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAA;AACvD,OAAO,KAAK,EAAE,iBAAiB,IAAI,qBAAqB,EAAE,MAAM,YAAY,CAAA;AAC5E,OAAO,KAAK,EACX,mCAAmC,EACnC,6CAA6C,EAC7C,6CAA6C,EAC7C,uBAAuB,EACvB,2BAA2B,EAC3B,gCAAgC,EAChC,MAAM,aAAa,CAAA;AACpB,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAA;AAC9C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA;AACpD,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAA;AAEzE;;;;GAIG;AACH,MAAM,MAAM,uBAAuB,GAAG,IAAI,CACzC,qBAAqB,EACrB,UAAU,GAAG,SAAS,GAAG,OAAO,GAAG,WAAW,CAC9C,CAAA;AAED;;GAEG;AACH,MAAM,MAAM,sBAAsB,GAAG,CAAC,IAAI,EAAE;IAC3C,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,CAAA;IACtB,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,EAAE,UAAU,CAAC,CAAA;IAClD,SAAS,EAAE,uBAAuB,CAAA;CAClC,KAAK,OAAO,CAAC;IACb,IAAI,EAAE,iBAAiB,CAAA;IACvB,MAAM,EAAE,KAAK,CACV,mCAAmC,GACnC,6CAA6C,GAC7C,6CAA6C,GAC7C,uBAAuB,GACvB,2BAA2B,GAC3B,gCAAgC,CAClC,CAAA;CACD,CAAC,CAAA;AAEF;;GAEG;AACH,MAAM,MAAM,iBAAiB,GAAG;IAC/B,YAAY,EAAE,CAAC,IAAI,EAAE;QACpB,YAAY,EAAE,WAAW,EAAE,CAAA;QAC3B,iBAAiB,EAAE,WAAW,CAAA;KAC9B,KAAK,OAAO,CAAC,OAAO,EAAE,CAAC,GAAG,OAAO,EAAE,CAAA;IACpC,YAAY,EAAE,CAAC,IAAI,EAAE;QAAE,QAAQ,EAAE,OAAO,EAAE,CAAA;KAAE,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAA;IACrE;;OAEG;IACH,oBAAoB,EAAE,WAAW,EAAE,CAAA;IACnC;;;;;;;;;;;;;;;;OAgBG;IACH,SAAS,EAAE,MAAM,CAAC,OAAO,MAAM,IAAI,MAAM,EAAE,GAAG,WAAW,MAAM,IAAI,MAAM,EAAE,EAAE,OAAO,CAAC,GAAG;QACvF,yBAAyB,CAAC,EAAE,2BAA2B,CAAA;KACvD,CAAA;CACD,CAAA"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/resolve-modules/plugins/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAA;AACvD,OAAO,KAAK,EAAE,iBAAiB,IAAI,qBAAqB,EAAE,MAAM,YAAY,CAAA;AAC5E,OAAO,KAAK,EACX,mCAAmC,EACnC,6CAA6C,EAC7C,6CAA6C,EAC7C,uBAAuB,EACvB,2BAA2B,EAC3B,gCAAgC,EAChC,0CAA0C,EAC1C,MAAM,aAAa,CAAA;AACpB,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAA;AAC9C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA;AACpD,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAA;AAEzE;;;;GAIG;AACH,MAAM,MAAM,uBAAuB,GAAG,IAAI,CACzC,qBAAqB,EACrB,UAAU,GAAG,SAAS,GAAG,OAAO,GAAG,WAAW,CAC9C,CAAA;AAED;;GAEG;AACH,MAAM,MAAM,sBAAsB,GAAG,CAAC,IAAI,EAAE;IAC3C,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,CAAA;IACtB,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,EAAE,UAAU,CAAC,CAAA;IAClD,SAAS,EAAE,uBAAuB,CAAA;CAClC,KAAK,OAAO,CAAC;IACb,IAAI,EAAE,iBAAiB,CAAA;IACvB,MAAM,EAAE,KAAK,CACV,mCAAmC,GACnC,6CAA6C,GAC7C,6CAA6C,GAC7C,uBAAuB,GACvB,2BAA2B,GAC3B,gCAAgC,GAChC,0CAA0C,CAC5C,CAAA;CACD,CAAC,CAAA;AAEF;;GAEG;AACH,MAAM,MAAM,iBAAiB,GAAG;IAC/B,YAAY,EAAE,CAAC,IAAI,EAAE;QACpB,YAAY,EAAE,WAAW,EAAE,CAAA;QAC3B,iBAAiB,EAAE,WAAW,CAAA;KAC9B,KAAK,OAAO,CAAC,OAAO,EAAE,CAAC,GAAG,OAAO,EAAE,CAAA;IACpC,YAAY,EAAE,CAAC,IAAI,EAAE;QAAE,QAAQ,EAAE,OAAO,EAAE,CAAA;KAAE,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAA;IACrE;;OAEG;IACH,oBAAoB,EAAE,WAAW,EAAE,CAAA;IACnC;;;;;;;;;;;;;;;;OAgBG;IACH,SAAS,EAAE,MAAM,CAAC,OAAO,MAAM,IAAI,MAAM,EAAE,GAAG,WAAW,MAAM,IAAI,MAAM,EAAE,EAAE,OAAO,CAAC,GAAG;QACvF,yBAAyB,CAAC,EAAE,2BAA2B,CAAA;KACvD,CAAA;CACD,CAAA"}
@@ -7,7 +7,7 @@ import { resolvePlugins } from "./plugins/resolvePlugins.js";
7
7
  import { TypeCompiler } from "@sinclair/typebox/compiler";
8
8
  const ModuleCompiler = TypeCompiler.Compile(InlangModule);
9
9
  export const resolveModules = async (args) => {
10
- const _import = args._import ?? createImport({ readFile: args.nodeishFs.readFile, fetch });
10
+ const _import = args._import ?? createImport({ readFile: args.nodeishFs.readFile });
11
11
  const moduleErrors = [];
12
12
  const allPlugins = [];
13
13
  const allMessageLintRules = [];
@@ -1,2 +1,3 @@
1
1
  export { createMessage } from "./createMessage.js";
2
+ export { createNodeishMemoryFs } from "@lix-js/fs";
2
3
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/test-utilities/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/test-utilities/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAClD,OAAO,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAA"}
@@ -1 +1,2 @@
1
1
  export { createMessage } from "./createMessage.js";
2
+ export { createNodeishMemoryFs } from "@lix-js/fs";
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@inlang/sdk",
3
3
  "type": "module",
4
- "version": "0.2.0",
4
+ "version": "0.3.0",
5
5
  "license": "Apache-2.0",
6
6
  "publishConfig": {
7
7
  "access": "public"
package/src/errors.ts CHANGED
@@ -32,15 +32,3 @@ export class PluginLoadMessagesError extends Error {
32
32
  this.name = "PluginLoadMessagesError"
33
33
  }
34
34
  }
35
-
36
- /**
37
- * Error when no package provides the API to handle messages.
38
- */
39
- export class NoPluginProvidesLoadOrSaveMessagesError extends Error {
40
- constructor() {
41
- super(
42
- "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.",
43
- ) // TODO: check if link is correct
44
- this.name = "NoPluginProvidesLoadOrSaveMessagesError"
45
- }
46
- }
package/src/index.ts CHANGED
@@ -19,7 +19,6 @@ export {
19
19
  ProjectFilePathNotFoundError,
20
20
  ProjectFileJSONSyntaxError,
21
21
  InvalidConfigError,
22
- NoPluginProvidesLoadOrSaveMessagesError,
23
22
  PluginLoadMessagesError,
24
23
  PluginSaveMessagesError,
25
24
  } from "./errors.js"
@@ -8,7 +8,6 @@ import {
8
8
  ProjectFilePathNotFoundError,
9
9
  ProjectFileJSONSyntaxError,
10
10
  InvalidConfigError,
11
- NoPluginProvidesLoadOrSaveMessagesError,
12
11
  } from "./errors.js"
13
12
  import { createNodeishMemoryFs } from "@lix-js/fs"
14
13
 
@@ -178,40 +177,6 @@ describe("initialization", () => {
178
177
  })
179
178
 
180
179
  describe("modules", () => {
181
- it("should return an error if no plugin defines readMessages", async () => {
182
- const $badImport: ImportFunction = async () =>
183
- ({
184
- default: { ...mockPlugin, loadMessages: undefined as any } as Plugin,
185
- } satisfies InlangModule)
186
-
187
- const fs = await createNodeishMemoryFs()
188
- await fs.writeFile("./project.inlang.json", JSON.stringify(config))
189
- const inlang = await openInlangProject({
190
- projectFilePath: "./project.inlang.json",
191
- nodeishFs: fs,
192
- _import: $badImport,
193
- })
194
-
195
- expect(inlang.errors()![0]).toBeInstanceOf(NoPluginProvidesLoadOrSaveMessagesError)
196
- })
197
-
198
- it("should return an error if no plugin defines writeMessages", async () => {
199
- const $badImport: ImportFunction = async () =>
200
- ({
201
- default: { ...mockPlugin, writeMessages: undefined as any } as Plugin,
202
- } satisfies InlangModule)
203
-
204
- const fs = createNodeishMemoryFs()
205
- await fs.writeFile("./project.inlang.json", JSON.stringify(config))
206
- const inlang = await openInlangProject({
207
- projectFilePath: "./project.inlang.json",
208
- nodeishFs: fs,
209
- _import: $badImport,
210
- })
211
-
212
- expect(inlang.errors()![0]).toBeInstanceOf(NoPluginProvidesLoadOrSaveMessagesError)
213
- })
214
-
215
180
  it("should return an error if an error occurs while resolving a plugin", async () => {
216
181
  const $badImport: ImportFunction = async () =>
217
182
  ({
@@ -227,7 +192,7 @@ describe("initialization", () => {
227
192
  _import: $badImport,
228
193
  })
229
194
 
230
- expect(inlang.errors()).toHaveLength(1)
195
+ expect(inlang.errors()).not.toHaveLength(0)
231
196
  })
232
197
  // it.todo("should throw if lintRules contain errors ???")
233
198
  // it.todo("should return meta data")
@@ -12,7 +12,6 @@ import {
12
12
  ProjectFilePathNotFoundError,
13
13
  ProjectFileJSONSyntaxError,
14
14
  InvalidConfigError,
15
- NoPluginProvidesLoadOrSaveMessagesError,
16
15
  PluginLoadMessagesError,
17
16
  PluginSaveMessagesError,
18
17
  } from "./errors.js"
@@ -87,13 +86,6 @@ export const openInlangProject = async (args: {
87
86
 
88
87
  loadModules({ config: conf, nodeishFs: args.nodeishFs, _import: args._import })
89
88
  .then((resolvedModules) => {
90
- // TODO move to resolveModules
91
- if (
92
- !resolvedModules.resolvedPluginApi.loadMessages ||
93
- !resolvedModules.resolvedPluginApi.saveMessages
94
- ) {
95
- throw new NoPluginProvidesLoadOrSaveMessagesError()
96
- }
97
89
  setResolvedModules(resolvedModules)
98
90
 
99
91
  // TODO: handle `detectedLanguageTags`
@@ -28,7 +28,6 @@ describe("$import", async () => {
28
28
 
29
29
  const _import = createImport({
30
30
  readFile: fs.readFile,
31
- fetch,
32
31
  })
33
32
 
34
33
  it("should import a module from a local path", async () => {
@@ -23,8 +23,6 @@ export type ImportFunction = (uri: string) => Promise<any>
23
23
  export function createImport(args: {
24
24
  /** the fs from which the file can be read */
25
25
  readFile: NodeishFilesystemSubset["readFile"]
26
- /** http client implementation */
27
- fetch: typeof fetch
28
26
  }): (uri: string) => ReturnType<typeof $import> {
29
27
  // resembles a native import api
30
28
  return (uri: string) => $import(uri, args)
@@ -37,16 +35,12 @@ async function $import(
37
35
  * Required to import from a local path.
38
36
  */
39
37
  readFile: NodeishFilesystemSubset["readFile"]
40
- /**
41
- * Required to import via network.
42
- */
43
- fetch: typeof fetch
44
38
  },
45
39
  ): Promise<any> {
46
40
  let moduleAsText: string
47
41
 
48
42
  if (uri.startsWith("http")) {
49
- moduleAsText = await (await options.fetch(uri)).text()
43
+ moduleAsText = await (await fetch(uri)).text()
50
44
  } else {
51
45
  moduleAsText = await options.readFile(normalizePath(uri), { encoding: "utf-8" })
52
46
  }
@@ -55,3 +55,11 @@ export class PluginReturnedInvalidCustomApiError extends PluginError {
55
55
  this.name = "PluginReturnedInvalidCustomApiError"
56
56
  }
57
57
  }
58
+
59
+ export class PluginsDoNotProvideLoadOrSaveMessagesError extends PluginError {
60
+ constructor(message: string, options: PluginErrorOptions) {
61
+ super(message, options)
62
+ this.name = "PluginsDoNotProvideLoadOrSaveMessagesError"
63
+ options.plugin = "plugin.inlang.missing"
64
+ }
65
+ }
@@ -8,6 +8,7 @@ import {
8
8
  PluginUsesReservedNamespaceError,
9
9
  PluginReturnedInvalidCustomApiError,
10
10
  PluginHasInvalidSchemaError,
11
+ PluginsDoNotProvideLoadOrSaveMessagesError,
11
12
  } from "./errors.js"
12
13
  import type { Plugin } from "@inlang/plugin"
13
14
 
@@ -57,7 +58,6 @@ describe("generally", () => {
57
58
  nodeishFs: {} as any,
58
59
  })
59
60
 
60
- expect(resolved.errors.length).toBe(1)
61
61
  expect(resolved.errors[0]).toBeInstanceOf(PluginHasInvalidSchemaError)
62
62
  })
63
63
 
@@ -77,7 +77,6 @@ describe("generally", () => {
77
77
  nodeishFs: {} as any,
78
78
  })
79
79
 
80
- expect(resolved.errors.length).toBe(1)
81
80
  expect(resolved.errors[0]).toBeInstanceOf(PluginUsesReservedNamespaceError)
82
81
  })
83
82
  })
@@ -131,9 +130,28 @@ describe("loadMessages", () => {
131
130
  settings: {},
132
131
  })
133
132
 
134
- expect(resolved.errors).toHaveLength(1)
135
133
  expect(resolved.errors[0]).toBeInstanceOf(PluginLoadMessagesFunctionAlreadyDefinedError)
136
134
  })
135
+
136
+ it("should return an error if no plugin defines loadMessages", async () => {
137
+ const mockPlugin: Plugin = {
138
+ meta: {
139
+ id: "plugin.namepsace.loadMessagesFirst",
140
+ description: { en: "My plugin description" },
141
+ displayName: { en: "My plugin" },
142
+ },
143
+ saveMessages: async () => undefined as any,
144
+ }
145
+
146
+ const resolved = await resolvePlugins({
147
+ plugins: [mockPlugin],
148
+ nodeishFs: {} as any,
149
+ settings: {},
150
+ })
151
+
152
+ expect(resolved.errors).toHaveLength(1)
153
+ expect(resolved.errors[0]).toBeInstanceOf(PluginsDoNotProvideLoadOrSaveMessagesError)
154
+ })
137
155
  })
138
156
 
139
157
  describe("saveMessages", () => {
@@ -144,6 +162,7 @@ describe("saveMessages", () => {
144
162
  description: { en: "My plugin description" },
145
163
  displayName: { en: "My plugin" },
146
164
  },
165
+ loadMessages: async () => undefined as any,
147
166
  saveMessages: async () => undefined as any,
148
167
  }
149
168
 
@@ -181,9 +200,27 @@ describe("saveMessages", () => {
181
200
  nodeishFs: {} as any,
182
201
  })
183
202
 
184
- expect(resolved.errors).toHaveLength(1)
185
203
  expect(resolved.errors[0]).toBeInstanceOf(PluginSaveMessagesFunctionAlreadyDefinedError)
186
204
  })
205
+
206
+ it("should return an error if no plugin defines saveMessages", async () => {
207
+ const mockPlugin: Plugin = {
208
+ meta: {
209
+ id: "plugin.namepsace.loadMessagesFirst",
210
+ description: { en: "My plugin description" },
211
+ displayName: { en: "My plugin" },
212
+ },
213
+ loadMessages: async () => undefined as any,
214
+ }
215
+
216
+ const resolved = await resolvePlugins({
217
+ plugins: [mockPlugin],
218
+ nodeishFs: {} as any,
219
+ settings: {},
220
+ })
221
+ expect(resolved.errors).toHaveLength(1)
222
+ expect(resolved.errors[0]).toBeInstanceOf(PluginsDoNotProvideLoadOrSaveMessagesError)
223
+ })
187
224
  })
188
225
 
189
226
  describe("detectedLanguageTags", () => {
@@ -304,7 +341,6 @@ describe("addCustomApi", () => {
304
341
  nodeishFs: {} as any,
305
342
  })
306
343
 
307
- expect(resolved.errors).toHaveLength(1)
308
344
  expect(resolved.errors[0]).toBeInstanceOf(PluginReturnedInvalidCustomApiError)
309
345
  })
310
346
 
@@ -5,6 +5,7 @@ import {
5
5
  PluginReturnedInvalidCustomApiError,
6
6
  PluginLoadMessagesFunctionAlreadyDefinedError,
7
7
  PluginSaveMessagesFunctionAlreadyDefinedError,
8
+ PluginsDoNotProvideLoadOrSaveMessagesError,
8
9
  PluginHasInvalidIdError,
9
10
  PluginHasInvalidSchemaError,
10
11
  PluginUsesReservedNamespaceError,
@@ -166,5 +167,18 @@ export const resolvePlugins: ResolvePluginsFunction = async (args) => {
166
167
  }
167
168
  }
168
169
 
170
+ // --- LOADMESSAGE / SAVEMESSAGE NOT DEFINED ---
171
+ if (
172
+ typeof result.data.loadMessages !== "function" ||
173
+ typeof result.data.saveMessages !== "function"
174
+ ) {
175
+ result.errors.push(
176
+ new PluginsDoNotProvideLoadOrSaveMessagesError(
177
+ "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.",
178
+ { plugin: "plugin.inlang.missing" },
179
+ ),
180
+ )
181
+ }
182
+
169
183
  return result
170
184
  }
@@ -7,6 +7,7 @@ import type {
7
7
  PluginHasInvalidIdError,
8
8
  PluginHasInvalidSchemaError,
9
9
  PluginUsesReservedNamespaceError,
10
+ PluginsDoNotProvideLoadOrSaveMessagesError,
10
11
  } from "./errors.js"
11
12
  import type { Message } from "@inlang/message"
12
13
  import type { JSONObject } from "@inlang/json-types"
@@ -38,6 +39,7 @@ export type ResolvePluginsFunction = (args: {
38
39
  | PluginHasInvalidIdError
39
40
  | PluginHasInvalidSchemaError
40
41
  | PluginUsesReservedNamespaceError
42
+ | PluginsDoNotProvideLoadOrSaveMessagesError
41
43
  >
42
44
  }>
43
45
 
@@ -17,7 +17,7 @@ import { TypeCompiler } from "@sinclair/typebox/compiler"
17
17
  const ModuleCompiler = TypeCompiler.Compile(InlangModule)
18
18
 
19
19
  export const resolveModules: ResolveModuleFunction = async (args) => {
20
- const _import = args._import ?? createImport({ readFile: args.nodeishFs.readFile, fetch })
20
+ const _import = args._import ?? createImport({ readFile: args.nodeishFs.readFile })
21
21
  const moduleErrors: Array<ModuleError> = []
22
22
 
23
23
  const allPlugins: Array<Plugin> = []
@@ -81,7 +81,7 @@ export const resolveModules: ResolveModuleFunction = async (args) => {
81
81
 
82
82
  const resolvedPlugins = await resolvePlugins({
83
83
  plugins: allPlugins,
84
- settings: args.config.settings as any, // TODO: fix type
84
+ settings: args.config.settings,
85
85
  nodeishFs: args.nodeishFs,
86
86
  })
87
87
 
@@ -1 +1,2 @@
1
1
  export { createMessage } from "./createMessage.js"
2
+ export { createNodeishMemoryFs } from "@lix-js/fs"