@inlang/sdk 0.1.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 (41) hide show
  1. package/README.md +4 -13
  2. package/dist/errors.d.ts +0 -6
  3. package/dist/errors.d.ts.map +1 -1
  4. package/dist/errors.js +0 -9
  5. package/dist/index.d.ts +1 -1
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +1 -1
  8. package/dist/messages/variant.js +3 -4
  9. package/dist/openInlangProject.d.ts.map +1 -1
  10. package/dist/openInlangProject.js +2 -7
  11. package/dist/openInlangProject.test.js +2 -28
  12. package/dist/resolve-modules/import.d.ts +0 -6
  13. package/dist/resolve-modules/import.d.ts.map +1 -1
  14. package/dist/resolve-modules/import.js +1 -1
  15. package/dist/resolve-modules/import.test.js +0 -1
  16. package/dist/resolve-modules/plugins/errors.d.ts +3 -0
  17. package/dist/resolve-modules/plugins/errors.d.ts.map +1 -1
  18. package/dist/resolve-modules/plugins/errors.js +7 -0
  19. package/dist/resolve-modules/plugins/resolvePlugins.d.ts.map +1 -1
  20. package/dist/resolve-modules/plugins/resolvePlugins.js +6 -1
  21. package/dist/resolve-modules/plugins/resolvePlugins.test.js +36 -6
  22. package/dist/resolve-modules/plugins/types.d.ts +2 -2
  23. package/dist/resolve-modules/plugins/types.d.ts.map +1 -1
  24. package/dist/resolve-modules/resolveModules.js +1 -1
  25. package/dist/test-utilities/index.d.ts +1 -0
  26. package/dist/test-utilities/index.d.ts.map +1 -1
  27. package/dist/test-utilities/index.js +1 -0
  28. package/package.json +1 -2
  29. package/src/errors.ts +0 -12
  30. package/src/index.ts +0 -1
  31. package/src/messages/variant.ts +2 -3
  32. package/src/openInlangProject.test.ts +1 -36
  33. package/src/openInlangProject.ts +1 -9
  34. package/src/resolve-modules/import.test.ts +0 -1
  35. package/src/resolve-modules/import.ts +1 -7
  36. package/src/resolve-modules/plugins/errors.ts +8 -0
  37. package/src/resolve-modules/plugins/resolvePlugins.test.ts +41 -5
  38. package/src/resolve-modules/plugins/resolvePlugins.ts +14 -0
  39. package/src/resolve-modules/plugins/types.ts +2 -0
  40. package/src/resolve-modules/resolveModules.ts +2 -2
  41. package/src/test-utilities/index.ts +1 -0
package/README.md CHANGED
@@ -2,24 +2,15 @@ Developer-first localization infrastructure that is built on git. Your git repos
2
2
 
3
3
  <div>
4
4
  <p align="center">
5
- <img width="300" src="https://cdn.jsdelivr.net/gh/inlang/inlang/assets/logo-white-background.png"/>
5
+ <img width="300" src="https://cdn.jsdelivr.net/gh/inlang/monorepo/inlang/assets/logo-white-background.png"/>
6
6
  </p>
7
7
  <h4 align="center">
8
8
  <!-- <a href="https://inlang.com/documentation" target="_blank">Get Started</a>
9
9
  · -->
10
- <a href="https://github.com/inlang/inlang/discussions" target="_blank">Discussions</a> · <a href="https://twitter.com/inlangHQ" target="_blank">Twitter</a>
10
+ <a href="https://github.com/inlang/monorepo/discussions" target="_blank">Discussions</a> · <a href="https://twitter.com/inlangHQ" target="_blank">Twitter</a>
11
11
  </h4>
12
12
  </div>
13
13
 
14
- # @inlang/core
14
+ # @inlang/sdk
15
15
 
16
- The core module bundles "core" modules that depend on each other and is everything one needs to build [plugins](https://inlang.com/documentation/plugins) or entire [apps](https://inlang.com/documentation/build-on-inlang) on inlang.
17
-
18
- ## Modules
19
-
20
- Click on the modules to get to their respective READMEs.
21
-
22
- - [@inlang/core/ast](https://github.com/inlang/inlang/tree/main/source-code/core/src/ast/) - The AST.
23
- - [@inlang/core/config](https://github.com/inlang/inlang/tree/main/source-code/core/src/config/) - The config that powers inlang.
24
- - [@inlang/core/query](https://github.com/inlang/inlang/tree/main/source-code/core/src/query/) - A query module for the AST.
25
- - [@inlang/core/utilities](https://github.com/inlang/inlang/tree/main/source-code/core/src/utilities/) - Utility types, functions, and more dealing that ease interactions with inlang, i18n, and localization.
16
+ The core module bundles "sdk" modules that depend on each other and is everything one needs to build [plugins](https://inlang.com/documentation/plugin) or entire [apps](https://inlang.com/documentation/develop-app) on inlang.
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";
@@ -104,10 +104,9 @@ const matchMostSpecificVariant = (message, languageTag, selectors) => {
104
104
  // resolve preferenceSelectors to match length and order of message selectors
105
105
  const resolvedSelectors = resolveSelector(message.selectors, selectors);
106
106
  const index = {};
107
- const languageVariants = message.variants.filter((variant) => variant.languageTag === languageTag);
108
- if (languageVariants.length === 0)
109
- return undefined;
110
- for (const variant of languageVariants) {
107
+ for (const variant of message.variants) {
108
+ if (variant.languageTag !== languageTag)
109
+ continue;
111
110
  let isMatch = true;
112
111
  //check if variant is a match
113
112
  for (const [key, value] of Object.entries(variant.match)) {
@@ -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
  })
@@ -98,7 +93,7 @@ export const openInlangProject = async (args) => {
98
93
  meta: rule.meta,
99
94
  module: resolvedModules()?.meta.find((m) => m.id.includes(rule.meta.id))?.module ??
100
95
  "Unknown module. You stumbled on a bug in inlang's source code. Please open an issue.",
101
- // default to warning, see https://github.com/inlang/inlang/issues/1254
96
+ // default to warning, see https://github.com/inlang/monorepo/issues/1254
102
97
  lintLevel: configValue.settings["project.messageLintRuleLevels"]?.[rule.meta.id] ?? "warning",
103
98
  }));
104
99
  };
@@ -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.1.0",
4
+ "version": "0.3.0",
5
5
  "license": "Apache-2.0",
6
6
  "publishConfig": {
7
7
  "access": "public"
@@ -45,7 +45,6 @@
45
45
  "ts-dedent": "2.2.0"
46
46
  },
47
47
  "devDependencies": {
48
- "@placeholder-company/js-code-style": "*",
49
48
  "@lix-js/fs": "*",
50
49
  "@types/throttle-debounce": "5.0.0",
51
50
  "@vitest/coverage-v8": "^0.33.0",
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"
@@ -154,10 +154,9 @@ const matchMostSpecificVariant = (
154
154
  const resolvedSelectors = resolveSelector(message.selectors, selectors)
155
155
  const index: Record<string, any> = {}
156
156
 
157
- const languageVariants = message.variants.filter((variant) => variant.languageTag === languageTag)
158
- if (languageVariants.length === 0) return undefined
157
+ for (const variant of message.variants) {
158
+ if (variant.languageTag !== languageTag) continue
159
159
 
160
- for (const variant of languageVariants) {
161
160
  let isMatch = true
162
161
 
163
162
  //check if variant is a match
@@ -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`
@@ -146,7 +138,7 @@ export const openInlangProject = async (args: {
146
138
  resolvedModules()?.meta.find((m) => m.id.includes(rule.meta.id))?.module ??
147
139
  "Unknown module. You stumbled on a bug in inlang's source code. Please open an issue.",
148
140
 
149
- // default to warning, see https://github.com/inlang/inlang/issues/1254
141
+ // default to warning, see https://github.com/inlang/monorepo/issues/1254
150
142
  lintLevel:
151
143
  configValue.settings["project.messageLintRuleLevels"]?.[rule.meta.id] ?? "warning",
152
144
  } satisfies InstalledMessageLintRule),
@@ -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"