@inlang/sdk 0.1.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 (170) hide show
  1. package/README.md +25 -0
  2. package/dist/adapter/solidAdapter.d.ts +32 -0
  3. package/dist/adapter/solidAdapter.d.ts.map +1 -0
  4. package/dist/adapter/solidAdapter.js +39 -0
  5. package/dist/adapter/solidAdapter.test.d.ts +2 -0
  6. package/dist/adapter/solidAdapter.test.d.ts.map +1 -0
  7. package/dist/adapter/solidAdapter.test.js +284 -0
  8. package/dist/api.d.ts +88 -0
  9. package/dist/api.d.ts.map +1 -0
  10. package/dist/api.js +1 -0
  11. package/dist/createMessageLintReportsQuery.d.ts +9 -0
  12. package/dist/createMessageLintReportsQuery.d.ts.map +1 -0
  13. package/dist/createMessageLintReportsQuery.js +48 -0
  14. package/dist/createMessagesQuery.d.ts +7 -0
  15. package/dist/createMessagesQuery.d.ts.map +1 -0
  16. package/dist/createMessagesQuery.js +57 -0
  17. package/dist/createMessagesQuery.test.d.ts +2 -0
  18. package/dist/createMessagesQuery.test.d.ts.map +1 -0
  19. package/dist/createMessagesQuery.test.js +304 -0
  20. package/dist/errors.d.ts +22 -0
  21. package/dist/errors.d.ts.map +1 -0
  22. package/dist/errors.js +39 -0
  23. package/dist/index.d.ts +15 -0
  24. package/dist/index.d.ts.map +1 -0
  25. package/dist/index.js +13 -0
  26. package/dist/lint/index.d.ts +3 -0
  27. package/dist/lint/index.d.ts.map +1 -0
  28. package/dist/lint/index.js +2 -0
  29. package/dist/lint/message/errors.d.ts +7 -0
  30. package/dist/lint/message/errors.d.ts.map +1 -0
  31. package/dist/lint/message/errors.js +9 -0
  32. package/dist/lint/message/lintMessages.d.ts +17 -0
  33. package/dist/lint/message/lintMessages.d.ts.map +1 -0
  34. package/dist/lint/message/lintMessages.js +12 -0
  35. package/dist/lint/message/lintMessages.test.d.ts +2 -0
  36. package/dist/lint/message/lintMessages.test.d.ts.map +1 -0
  37. package/dist/lint/message/lintMessages.test.js +105 -0
  38. package/dist/lint/message/lintSingleMessage.d.ts +23 -0
  39. package/dist/lint/message/lintSingleMessage.d.ts.map +1 -0
  40. package/dist/lint/message/lintSingleMessage.js +36 -0
  41. package/dist/lint/message/lintSingleMessage.test.d.ts +2 -0
  42. package/dist/lint/message/lintSingleMessage.test.d.ts.map +1 -0
  43. package/dist/lint/message/lintSingleMessage.test.js +155 -0
  44. package/dist/messages/errors.d.ts +13 -0
  45. package/dist/messages/errors.d.ts.map +1 -0
  46. package/dist/messages/errors.js +18 -0
  47. package/dist/messages/index.d.ts +3 -0
  48. package/dist/messages/index.d.ts.map +1 -0
  49. package/dist/messages/index.js +2 -0
  50. package/dist/messages/variant.d.ts +46 -0
  51. package/dist/messages/variant.d.ts.map +1 -0
  52. package/dist/messages/variant.js +177 -0
  53. package/dist/messages/variant.test.d.ts +2 -0
  54. package/dist/messages/variant.test.d.ts.map +1 -0
  55. package/dist/messages/variant.test.js +379 -0
  56. package/dist/openInlangProject.d.ts +18 -0
  57. package/dist/openInlangProject.d.ts.map +1 -0
  58. package/dist/openInlangProject.js +226 -0
  59. package/dist/openInlangProject.test.d.ts +2 -0
  60. package/dist/openInlangProject.test.d.ts.map +1 -0
  61. package/dist/openInlangProject.test.js +627 -0
  62. package/dist/parseConfig.d.ts +8 -0
  63. package/dist/parseConfig.d.ts.map +1 -0
  64. package/dist/parseConfig.js +26 -0
  65. package/dist/reactivity/map.d.ts +66 -0
  66. package/dist/reactivity/map.d.ts.map +1 -0
  67. package/dist/reactivity/map.js +143 -0
  68. package/dist/reactivity/solid.d.ts +12 -0
  69. package/dist/reactivity/solid.d.ts.map +1 -0
  70. package/dist/reactivity/solid.js +13 -0
  71. package/dist/reactivity/trigger.d.ts +11 -0
  72. package/dist/reactivity/trigger.d.ts.map +1 -0
  73. package/dist/reactivity/trigger.js +46 -0
  74. package/dist/resolve-modules/errors.d.ts +34 -0
  75. package/dist/resolve-modules/errors.d.ts.map +1 -0
  76. package/dist/resolve-modules/errors.js +35 -0
  77. package/dist/resolve-modules/import.d.ts +35 -0
  78. package/dist/resolve-modules/import.d.ts.map +1 -0
  79. package/dist/resolve-modules/import.js +40 -0
  80. package/dist/resolve-modules/import.test.d.ts +2 -0
  81. package/dist/resolve-modules/import.test.d.ts.map +1 -0
  82. package/dist/resolve-modules/import.test.js +45 -0
  83. package/dist/resolve-modules/index.d.ts +3 -0
  84. package/dist/resolve-modules/index.d.ts.map +1 -0
  85. package/dist/resolve-modules/index.js +2 -0
  86. package/dist/resolve-modules/message-lint-rules/errors.d.ts +8 -0
  87. package/dist/resolve-modules/message-lint-rules/errors.d.ts.map +1 -0
  88. package/dist/resolve-modules/message-lint-rules/errors.js +8 -0
  89. package/dist/resolve-modules/message-lint-rules/resolveMessageLintRules.d.ts +9 -0
  90. package/dist/resolve-modules/message-lint-rules/resolveMessageLintRules.d.ts.map +1 -0
  91. package/dist/resolve-modules/message-lint-rules/resolveMessageLintRules.js +21 -0
  92. package/dist/resolve-modules/plugins/errors.d.ts +28 -0
  93. package/dist/resolve-modules/plugins/errors.d.ts.map +1 -0
  94. package/dist/resolve-modules/plugins/errors.js +44 -0
  95. package/dist/resolve-modules/plugins/resolvePlugins.d.ts +3 -0
  96. package/dist/resolve-modules/plugins/resolvePlugins.d.ts.map +1 -0
  97. package/dist/resolve-modules/plugins/resolvePlugins.js +108 -0
  98. package/dist/resolve-modules/plugins/resolvePlugins.test.d.ts +2 -0
  99. package/dist/resolve-modules/plugins/resolvePlugins.test.d.ts.map +1 -0
  100. package/dist/resolve-modules/plugins/resolvePlugins.test.js +289 -0
  101. package/dist/resolve-modules/plugins/types.d.ts +60 -0
  102. package/dist/resolve-modules/plugins/types.d.ts.map +1 -0
  103. package/dist/resolve-modules/plugins/types.js +1 -0
  104. package/dist/resolve-modules/plugins/types.test.d.ts +2 -0
  105. package/dist/resolve-modules/plugins/types.test.d.ts.map +1 -0
  106. package/dist/resolve-modules/plugins/types.test.js +49 -0
  107. package/dist/resolve-modules/resolveModules.d.ts +3 -0
  108. package/dist/resolve-modules/resolveModules.d.ts.map +1 -0
  109. package/dist/resolve-modules/resolveModules.js +70 -0
  110. package/dist/resolve-modules/resolveModules.test.d.ts +2 -0
  111. package/dist/resolve-modules/resolveModules.test.d.ts.map +1 -0
  112. package/dist/resolve-modules/resolveModules.test.js +143 -0
  113. package/dist/resolve-modules/types.d.ts +62 -0
  114. package/dist/resolve-modules/types.d.ts.map +1 -0
  115. package/dist/resolve-modules/types.js +1 -0
  116. package/dist/test-utilities/createMessage.d.ts +17 -0
  117. package/dist/test-utilities/createMessage.d.ts.map +1 -0
  118. package/dist/test-utilities/createMessage.js +16 -0
  119. package/dist/test-utilities/createMessage.test.d.ts +2 -0
  120. package/dist/test-utilities/createMessage.test.d.ts.map +1 -0
  121. package/dist/test-utilities/createMessage.test.js +91 -0
  122. package/dist/test-utilities/index.d.ts +2 -0
  123. package/dist/test-utilities/index.d.ts.map +1 -0
  124. package/dist/test-utilities/index.js +1 -0
  125. package/dist/versionedInterfaces.d.ts +8 -0
  126. package/dist/versionedInterfaces.d.ts.map +1 -0
  127. package/dist/versionedInterfaces.js +8 -0
  128. package/package.json +58 -0
  129. package/src/adapter/solidAdapter.test.ts +363 -0
  130. package/src/adapter/solidAdapter.ts +77 -0
  131. package/src/api.ts +86 -0
  132. package/src/createMessageLintReportsQuery.ts +77 -0
  133. package/src/createMessagesQuery.test.ts +435 -0
  134. package/src/createMessagesQuery.ts +64 -0
  135. package/src/errors.ts +46 -0
  136. package/src/index.ts +29 -0
  137. package/src/lint/index.ts +2 -0
  138. package/src/lint/message/errors.ts +9 -0
  139. package/src/lint/message/lintMessages.test.ts +122 -0
  140. package/src/lint/message/lintMessages.ts +33 -0
  141. package/src/lint/message/lintSingleMessage.test.ts +183 -0
  142. package/src/lint/message/lintSingleMessage.ts +62 -0
  143. package/src/messages/errors.ts +25 -0
  144. package/src/messages/index.ts +2 -0
  145. package/src/messages/variant.test.ts +444 -0
  146. package/src/messages/variant.ts +242 -0
  147. package/src/openInlangProject.test.ts +734 -0
  148. package/src/openInlangProject.ts +337 -0
  149. package/src/parseConfig.ts +33 -0
  150. package/src/reactivity/map.ts +135 -0
  151. package/src/reactivity/solid.ts +36 -0
  152. package/src/reactivity/trigger.ts +46 -0
  153. package/src/resolve-modules/errors.ts +39 -0
  154. package/src/resolve-modules/import.test.ts +58 -0
  155. package/src/resolve-modules/import.ts +69 -0
  156. package/src/resolve-modules/index.ts +2 -0
  157. package/src/resolve-modules/message-lint-rules/errors.ts +9 -0
  158. package/src/resolve-modules/message-lint-rules/resolveMessageLintRules.ts +24 -0
  159. package/src/resolve-modules/plugins/errors.ts +57 -0
  160. package/src/resolve-modules/plugins/resolvePlugins.test.ts +340 -0
  161. package/src/resolve-modules/plugins/resolvePlugins.ts +170 -0
  162. package/src/resolve-modules/plugins/types.test.ts +57 -0
  163. package/src/resolve-modules/plugins/types.ts +77 -0
  164. package/src/resolve-modules/resolveModules.test.ts +176 -0
  165. package/src/resolve-modules/resolveModules.ts +97 -0
  166. package/src/resolve-modules/types.ts +71 -0
  167. package/src/test-utilities/createMessage.test.ts +100 -0
  168. package/src/test-utilities/createMessage.ts +20 -0
  169. package/src/test-utilities/index.ts +1 -0
  170. package/src/versionedInterfaces.ts +9 -0
package/README.md ADDED
@@ -0,0 +1,25 @@
1
+ Developer-first localization infrastructure that is built on git. Your git repository is the single source of truth for localization for collaboration and automation.
2
+
3
+ <div>
4
+ <p align="center">
5
+ <img width="300" src="https://cdn.jsdelivr.net/gh/inlang/inlang/assets/logo-white-background.png"/>
6
+ </p>
7
+ <h4 align="center">
8
+ <!-- <a href="https://inlang.com/documentation" target="_blank">Get Started</a>
9
+ · -->
10
+ <a href="https://github.com/inlang/inlang/discussions" target="_blank">Discussions</a> · <a href="https://twitter.com/inlangHQ" target="_blank">Twitter</a>
11
+ </h4>
12
+ </div>
13
+
14
+ # @inlang/core
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.
@@ -0,0 +1,32 @@
1
+ import type { InlangProject, MessageLintReportsQueryApi } from "../api.js";
2
+ import { type from as solidFrom } from "../reactivity/solid.js";
3
+ import type { MessageQueryApi } from "@inlang/sdk";
4
+ export declare const solidAdapter: (project: InlangProject, arg: {
5
+ from: typeof solidFrom;
6
+ }) => InlangProjectWithSolidAdapter;
7
+ export type InlangProjectWithSolidAdapter = {
8
+ customApi: () => ReturnType<InlangProject["customApi"]>;
9
+ installed: {
10
+ plugins: () => ReturnType<InlangProject["installed"]["plugins"]>;
11
+ messageLintRules: () => ReturnType<InlangProject["installed"]["messageLintRules"]>;
12
+ };
13
+ errors: () => ReturnType<InlangProject["errors"]>;
14
+ config: () => ReturnType<InlangProject["config"]>;
15
+ setConfig: InlangProject["setConfig"];
16
+ query: {
17
+ messages: {
18
+ create: MessageQueryApi["create"];
19
+ update: MessageQueryApi["update"];
20
+ delete: MessageQueryApi["delete"];
21
+ upsert: MessageQueryApi["upsert"];
22
+ get: MessageQueryApi["get"];
23
+ getAll: () => ReturnType<MessageQueryApi["getAll"]>;
24
+ includedMessageIds: () => ReturnType<MessageQueryApi["includedMessageIds"]>;
25
+ };
26
+ messageLintReports: {
27
+ get: MessageLintReportsQueryApi["get"];
28
+ getAll: () => ReturnType<MessageLintReportsQueryApi["getAll"]>;
29
+ };
30
+ };
31
+ };
32
+ //# sourceMappingURL=solidAdapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"solidAdapter.d.ts","sourceRoot":"","sources":["../../src/adapter/solidAdapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,0BAA0B,EAAE,MAAM,WAAW,CAAA;AAC1E,OAAO,EAAc,KAAK,IAAI,IAAI,SAAS,EAAE,MAAM,wBAAwB,CAAA;AAC3E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAElD,eAAO,MAAM,YAAY,YACf,aAAa,OACjB;IACJ,IAAI,EAAE,gBAAgB,CAAA;CACtB,KACC,6BAmCF,CAAA;AAED,MAAM,MAAM,6BAA6B,GAAG;IAC3C,SAAS,EAAE,MAAM,UAAU,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC,CAAA;IACvD,SAAS,EAAE;QACV,OAAO,EAAE,MAAM,UAAU,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC,SAAS,CAAC,CAAC,CAAA;QAChE,gBAAgB,EAAE,MAAM,UAAU,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAA;KAClF,CAAA;IACD,MAAM,EAAE,MAAM,UAAU,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC,CAAA;IACjD,MAAM,EAAE,MAAM,UAAU,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC,CAAA;IACjD,SAAS,EAAE,aAAa,CAAC,WAAW,CAAC,CAAA;IACrC,KAAK,EAAE;QACN,QAAQ,EAAE;YACT,MAAM,EAAE,eAAe,CAAC,QAAQ,CAAC,CAAA;YACjC,MAAM,EAAE,eAAe,CAAC,QAAQ,CAAC,CAAA;YACjC,MAAM,EAAE,eAAe,CAAC,QAAQ,CAAC,CAAA;YACjC,MAAM,EAAE,eAAe,CAAC,QAAQ,CAAC,CAAA;YACjC,GAAG,EAAE,eAAe,CAAC,KAAK,CAAC,CAAA;YAE3B,MAAM,EAAE,MAAM,UAAU,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC,CAAA;YACnD,kBAAkB,EAAE,MAAM,UAAU,CAAC,eAAe,CAAC,oBAAoB,CAAC,CAAC,CAAA;SAC3E,CAAA;QACD,kBAAkB,EAAE;YACnB,GAAG,EAAE,0BAA0B,CAAC,KAAK,CAAC,CAAA;YACtC,MAAM,EAAE,MAAM,UAAU,CAAC,0BAA0B,CAAC,QAAQ,CAAC,CAAC,CAAA;SAC9D,CAAA;KACD,CAAA;CACD,CAAA"}
@@ -0,0 +1,39 @@
1
+ import { observable } from "../reactivity/solid.js";
2
+ export const solidAdapter = (project, arg) => {
3
+ const convert = (signal) => {
4
+ return arg.from(observable(signal));
5
+ };
6
+ return {
7
+ customApi: convert(project.customApi),
8
+ config: convert(project.config),
9
+ errors: convert(project.errors),
10
+ installed: {
11
+ messageLintRules: convert(project.installed.messageLintRules),
12
+ plugins: convert(project.installed.plugins),
13
+ },
14
+ setConfig: project.setConfig,
15
+ query: {
16
+ messages: {
17
+ create: project.query.messages.create,
18
+ update: project.query.messages.update,
19
+ delete: project.query.messages.delete,
20
+ upsert: project.query.messages.upsert,
21
+ get: project.query.messages.get,
22
+ // get: (args) => {
23
+ // const [message, setMessage] = createSignal<Message | undefined>()
24
+ // project.query.messages.get.subscribe(args, setMessage)
25
+ // return message()
26
+ // },
27
+ getAll: convert(project.query.messages.getAll),
28
+ includedMessageIds: convert(project.query.messages.includedMessageIds),
29
+ },
30
+ messageLintReports: {
31
+ get: project.query.messageLintReports.get,
32
+ getAll: convert(project.query.messageLintReports.getAll),
33
+ },
34
+ },
35
+ };
36
+ };
37
+ // const x = {} as InlangProjectWithSolidAdapter
38
+ // x.query.lintReports.getAll()
39
+ // console.log(await x.lint())
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=solidAdapter.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"solidAdapter.test.d.ts","sourceRoot":"","sources":["../../src/adapter/solidAdapter.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,284 @@
1
+ /* eslint-disable @typescript-eslint/no-non-null-assertion */
2
+ import { describe, it, expect } from "vitest";
3
+ import { createEffect, from, createRoot } from "../reactivity/solid.js";
4
+ import { solidAdapter } from "./solidAdapter.js";
5
+ import { openInlangProject } from "../openInlangProject.js";
6
+ import { createNodeishMemoryFs } from "@lix-js/fs";
7
+ // ------------------------------------------------------------------------------------------------
8
+ const config = {
9
+ sourceLanguageTag: "en",
10
+ languageTags: ["en"],
11
+ modules: ["plugin.js", "plugin2.js"],
12
+ settings: {
13
+ "project.messageLintRuleLevels": {
14
+ "messageLintRule.inlang.missingTranslation": "error",
15
+ },
16
+ "plugin.inlang.i18next": {
17
+ pathPattern: "./examples/example01/{languageTag}.json",
18
+ variableReferencePattern: ["{", "}"],
19
+ },
20
+ },
21
+ };
22
+ const mockPlugin = {
23
+ meta: {
24
+ id: "plugin.inlang.i18next",
25
+ description: { en: "Mock plugin description" },
26
+ displayName: { en: "Mock Plugin" },
27
+ },
28
+ loadMessages: () => exampleMessages,
29
+ saveMessages: () => undefined,
30
+ };
31
+ // TODO: use `createMessage` utility
32
+ const exampleMessages = [
33
+ {
34
+ id: "a",
35
+ selectors: [],
36
+ variants: [
37
+ {
38
+ languageTag: "en",
39
+ match: {},
40
+ pattern: [
41
+ {
42
+ type: "Text",
43
+ value: "test",
44
+ },
45
+ ],
46
+ },
47
+ ],
48
+ },
49
+ {
50
+ id: "b",
51
+ selectors: [],
52
+ variants: [
53
+ {
54
+ languageTag: "en",
55
+ match: {},
56
+ pattern: [
57
+ {
58
+ type: "Text",
59
+ value: "test",
60
+ },
61
+ ],
62
+ },
63
+ ],
64
+ },
65
+ ];
66
+ const mockLintRule = {
67
+ meta: {
68
+ id: "messageLintRule.namespace.mock",
69
+ description: { en: "Mock lint rule description" },
70
+ displayName: { en: "Mock Lint Rule" },
71
+ },
72
+ message: () => undefined,
73
+ };
74
+ const $import = async (name) => ({
75
+ default: name === "plugin.js" ? mockPlugin : mockLintRule,
76
+ });
77
+ // ------------------------------------------------------------------------------------------------
78
+ describe("config", () => {
79
+ it("should react to changes in config", async () => {
80
+ const fs = createNodeishMemoryFs();
81
+ await fs.writeFile("./project.inlang.json", JSON.stringify(config));
82
+ const inlang = solidAdapter(await openInlangProject({
83
+ projectFilePath: "./project.inlang.json",
84
+ nodeishFs: fs,
85
+ _import: $import,
86
+ }), { from });
87
+ let counter = 0;
88
+ createEffect(() => {
89
+ inlang.config();
90
+ counter += 1;
91
+ });
92
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
93
+ const newConfig = { ...inlang.config(), languageTags: ["en", "de"] };
94
+ inlang.setConfig(newConfig);
95
+ // TODO: how can we await `setConfig` correctly
96
+ await new Promise((resolve) => setTimeout(resolve, 0));
97
+ expect(counter).toBe(2); // 2 times because effect creation + set
98
+ expect(inlang.config()).toStrictEqual(newConfig);
99
+ });
100
+ });
101
+ describe("installed", () => {
102
+ it("react to changes that are unrelated to installed items", async () => {
103
+ const fs = createNodeishMemoryFs();
104
+ await fs.writeFile("./project.inlang.json", JSON.stringify(config));
105
+ const inlang = solidAdapter(await openInlangProject({
106
+ projectFilePath: "./project.inlang.json",
107
+ nodeishFs: fs,
108
+ _import: $import,
109
+ }), { from });
110
+ let counterPlugins = 0;
111
+ let counterLint = 0;
112
+ createEffect(() => {
113
+ inlang.installed.plugins();
114
+ counterPlugins += 1;
115
+ });
116
+ createEffect(() => {
117
+ inlang.installed.messageLintRules();
118
+ counterLint += 1;
119
+ });
120
+ inlang.setConfig({ ...inlang.config(), languageTags: ["en", "fr"] });
121
+ // TODO: how can we await `setConfig` correctly
122
+ await new Promise((resolve) => setTimeout(resolve, 0));
123
+ expect(counterPlugins).toBe(2); // 2 times because effect creation + set
124
+ expect(counterLint).toBe(2); // 2 times because effect creation + set
125
+ });
126
+ });
127
+ describe("messages", () => {
128
+ it("should react to changes in config", async () => {
129
+ const fs = createNodeishMemoryFs();
130
+ const mockConfig = {
131
+ sourceLanguageTag: "en",
132
+ languageTags: ["en", "de"],
133
+ modules: ["./plugin-a.js"],
134
+ settings: {
135
+ "library.inlang.paraglideJsSveltekit": {
136
+ languageNegotiation: {
137
+ strategies: [
138
+ {
139
+ type: "localStorage",
140
+ },
141
+ ],
142
+ },
143
+ },
144
+ },
145
+ };
146
+ const mockPlugin = {
147
+ meta: {
148
+ id: "plugin.mock.id",
149
+ displayName: {
150
+ en: "hello",
151
+ },
152
+ description: {
153
+ en: "wo",
154
+ },
155
+ },
156
+ loadMessages: ({ languageTags }) => (languageTags.length ? exampleMessages : []),
157
+ saveMessages: () => undefined,
158
+ };
159
+ const mockImport = async () => ({ default: mockPlugin });
160
+ await fs.writeFile("./project.inlang.json", JSON.stringify(mockConfig));
161
+ const inlang = solidAdapter(await openInlangProject({
162
+ projectFilePath: "./project.inlang.json",
163
+ nodeishFs: fs,
164
+ _import: mockImport,
165
+ }), { from });
166
+ let counter = 0;
167
+ createEffect(() => {
168
+ inlang.query.messages.getAll();
169
+ counter += 1;
170
+ });
171
+ expect(Object.values(inlang.query.messages.getAll()).length).toBe(2);
172
+ inlang.setConfig({ ...inlang.config(), languageTags: [] });
173
+ // TODO: how can we await `setConfig` correctly
174
+ await new Promise((resolve) => setTimeout(resolve, 0));
175
+ expect(counter).toBe(2); // 2 times because effect creation + set
176
+ expect(Object.values(inlang.query.messages.getAll()).length).toBe(0);
177
+ });
178
+ it("should react to changes in messages", async () => {
179
+ const fs = createNodeishMemoryFs();
180
+ await fs.writeFile("./project.inlang.json", JSON.stringify(config));
181
+ const inlang = solidAdapter(await openInlangProject({
182
+ projectFilePath: "./project.inlang.json",
183
+ nodeishFs: fs,
184
+ _import: $import,
185
+ }), { from });
186
+ let counter = 0;
187
+ createEffect(() => {
188
+ inlang.query.messages.getAll();
189
+ counter += 1;
190
+ });
191
+ const messagesBefore = inlang.query.messages.getAll;
192
+ expect(Object.values(messagesBefore()).length).toBe(2);
193
+ expect((Object.values(messagesBefore())[0]?.variants.find((variant) => variant.languageTag === "en")
194
+ ?.pattern[0]).value).toBe("test");
195
+ inlang.query.messages.update({
196
+ where: { id: "a" },
197
+ // TODO: use `createMessage` utility
198
+ data: {
199
+ ...exampleMessages[0],
200
+ variants: [
201
+ {
202
+ languageTag: "en",
203
+ match: {},
204
+ pattern: [
205
+ {
206
+ type: "Text",
207
+ value: "test2",
208
+ },
209
+ ],
210
+ },
211
+ ],
212
+ },
213
+ });
214
+ expect(counter).toBe(2); // 2 times because effect creation + set
215
+ const messagesAfter = inlang.query.messages.getAll;
216
+ expect(Object.values(messagesAfter()).length).toBe(2);
217
+ expect((Object.values(messagesAfter())[0]?.variants.find((variant) => variant.languageTag === "en")
218
+ ?.pattern[0]).value).toBe("test2");
219
+ });
220
+ });
221
+ describe("lint", () => {
222
+ it.todo("should react to changes in config", async () => {
223
+ await createRoot(async () => {
224
+ const fs = createNodeishMemoryFs();
225
+ await fs.writeFile("./inlang.config.json", JSON.stringify(config));
226
+ const inlang = solidAdapter(await openInlangProject({
227
+ projectFilePath: "./inlang.config.json",
228
+ nodeishFs: fs,
229
+ _import: $import,
230
+ }), { from });
231
+ let counter = 0;
232
+ createEffect(() => {
233
+ inlang.query.messageLintReports.getAll();
234
+ counter += 1;
235
+ });
236
+ const newConfig = { ...inlang.config(), languageTags: ["en", "de"] };
237
+ inlang.setConfig(newConfig);
238
+ expect(counter).toBe(1);
239
+ expect(inlang.query.messageLintReports.getAll()).toEqual([]);
240
+ await new Promise((resolve) => setTimeout(resolve, 510));
241
+ const newConfig2 = { ...inlang.config(), languageTags: ["en", "de", "fr"] };
242
+ inlang.setConfig(newConfig2);
243
+ expect(counter).toBe(9);
244
+ expect(inlang.query.messageLintReports.getAll()).toEqual([]);
245
+ });
246
+ });
247
+ it.todo("should react to changes to packages");
248
+ it.todo("should react to changes to modules");
249
+ it.todo("should react to changes to messages", async () => {
250
+ await createRoot(async () => {
251
+ const fs = createNodeishMemoryFs();
252
+ await fs.writeFile("./inlang.config.json", JSON.stringify(config));
253
+ const inlang = solidAdapter(await openInlangProject({
254
+ projectFilePath: "./inlang.config.json",
255
+ nodeishFs: fs,
256
+ _import: $import,
257
+ }), { from });
258
+ let counter = 0;
259
+ createEffect(() => {
260
+ inlang.query.messageLintReports.getAll();
261
+ counter += 1;
262
+ });
263
+ inlang.query.messages.update({
264
+ where: { id: "a" },
265
+ data: {
266
+ ...exampleMessages[0],
267
+ variants: [{ languageTag: "en", match: {}, pattern: [{ type: "Text", value: "new" }] }],
268
+ },
269
+ });
270
+ expect(counter).toBe(1);
271
+ expect(inlang.query.messageLintReports.getAll()).toEqual([]);
272
+ await new Promise((resolve) => setTimeout(resolve, 510));
273
+ inlang.query.messages.update({
274
+ where: { id: "a" },
275
+ data: {
276
+ ...exampleMessages[0],
277
+ variants: [{ languageTag: "en", match: {}, pattern: [{ type: "Text", value: "new" }] }],
278
+ },
279
+ });
280
+ expect(counter).toBe(6);
281
+ expect(inlang.query.messageLintReports.getAll()).toEqual([]);
282
+ });
283
+ });
284
+ });
package/dist/api.d.ts ADDED
@@ -0,0 +1,88 @@
1
+ import type { Result } from "@inlang/result";
2
+ import type * as RuntimeError from "./errors.js";
3
+ import type * as ModuleResolutionError from "./resolve-modules/errors.js";
4
+ import type { MessageLintLevel, MessageLintRule, Message, Plugin, ProjectConfig, MessageLintReport } from "./versionedInterfaces.js";
5
+ import type { ResolvedPluginApi } from "./resolve-modules/plugins/types.js";
6
+ export type InstalledPlugin = {
7
+ meta: Plugin["meta"];
8
+ /**
9
+ * The module which the plugin is installed from.
10
+ */
11
+ module: string;
12
+ };
13
+ export type InstalledMessageLintRule = {
14
+ meta: MessageLintRule["meta"];
15
+ /**
16
+ * The module which the lint rule is installed from.
17
+ */
18
+ module: string;
19
+ lintLevel: MessageLintLevel;
20
+ };
21
+ export type InlangProject = {
22
+ installed: {
23
+ plugins: Subscribable<InstalledPlugin[]>;
24
+ messageLintRules: Subscribable<InstalledMessageLintRule[]>;
25
+ };
26
+ errors: Subscribable<((typeof ModuleResolutionError)[keyof typeof ModuleResolutionError] | Error)[]>;
27
+ customApi: Subscribable<ResolvedPluginApi["customApi"]>;
28
+ config: Subscribable<ProjectConfig | undefined>;
29
+ setConfig: (config: ProjectConfig) => Result<void, RuntimeError.InvalidConfigError>;
30
+ query: {
31
+ messages: MessageQueryApi;
32
+ messageLintReports: MessageLintReportsQueryApi;
33
+ };
34
+ };
35
+ export type Subscribable<Value> = {
36
+ (): Value;
37
+ subscribe: (callback: (value: Value) => void) => void;
38
+ };
39
+ export type MessageQueryApi = {
40
+ create: (args: {
41
+ data: Message;
42
+ }) => boolean;
43
+ get: ((args: {
44
+ where: {
45
+ id: Message["id"];
46
+ };
47
+ }) => Readonly<Message>) & {
48
+ subscribe: (args: {
49
+ where: {
50
+ id: Message["id"];
51
+ };
52
+ }, callback: (message: Message) => void) => void;
53
+ };
54
+ includedMessageIds: Subscribable<Message["id"][]>;
55
+ getAll: Subscribable<Readonly<Message[]>>;
56
+ update: (args: {
57
+ where: {
58
+ id: Message["id"];
59
+ };
60
+ data: Partial<Message>;
61
+ }) => boolean;
62
+ upsert: (args: {
63
+ where: {
64
+ id: Message["id"];
65
+ };
66
+ data: Message;
67
+ }) => void;
68
+ delete: (args: {
69
+ where: {
70
+ id: Message["id"];
71
+ };
72
+ }) => boolean;
73
+ };
74
+ export type MessageLintReportsQueryApi = {
75
+ getAll: Subscribable<MessageLintReport[]>;
76
+ get: ((args: {
77
+ where: {
78
+ messageId: MessageLintReport["messageId"];
79
+ };
80
+ }) => Readonly<MessageLintReport[]>) & {
81
+ subscribe: (args: {
82
+ where: {
83
+ messageId: MessageLintReport["messageId"];
84
+ };
85
+ }, callback: (MessageLintRules: Readonly<MessageLintReport[]>) => void) => void;
86
+ };
87
+ };
88
+ //# sourceMappingURL=api.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"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"}
package/dist/api.js ADDED
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,9 @@
1
+ import type { InlangProject, InstalledMessageLintRule } from "./api.js";
2
+ import type { ProjectConfig } from "@inlang/project-config";
3
+ import type { resolveModules } from "./resolve-modules/index.js";
4
+ import type { Message } from "./versionedInterfaces.js";
5
+ /**
6
+ * Creates a reactive query API for messages.
7
+ */
8
+ export declare function createMessageLintReportsQuery(messages: () => Array<Message> | undefined, config: () => ProjectConfig | undefined, installedMessageLintRules: () => Array<InstalledMessageLintRule>, resolvedModules: () => Awaited<ReturnType<typeof resolveModules>> | undefined): InlangProject["query"]["messageLintReports"];
9
+ //# sourceMappingURL=createMessageLintReportsQuery.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createMessageLintReportsQuery.d.ts","sourceRoot":"","sources":["../src/createMessageLintReportsQuery.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,wBAAwB,EAA8B,MAAM,UAAU,CAAA;AACnG,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAA;AAC3D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAA;AAChE,OAAO,KAAK,EAIX,OAAO,EACP,MAAM,0BAA0B,CAAA;AAIjC;;GAEG;AACH,wBAAgB,6BAA6B,CAC5C,QAAQ,EAAE,MAAM,KAAK,CAAC,OAAO,CAAC,GAAG,SAAS,EAC1C,MAAM,EAAE,MAAM,aAAa,GAAG,SAAS,EACvC,yBAAyB,EAAE,MAAM,KAAK,CAAC,wBAAwB,CAAC,EAChE,eAAe,EAAE,MAAM,OAAO,CAAC,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC,GAAG,SAAS,GAC3E,aAAa,CAAC,OAAO,CAAC,CAAC,oBAAoB,CAAC,CAsD9C"}
@@ -0,0 +1,48 @@
1
+ import { createEffect } from "./reactivity/solid.js";
2
+ import { createSubscribable } from "./openInlangProject.js";
3
+ import { lintSingleMessage } from "./lint/index.js";
4
+ import { ReactiveMap } from "./reactivity/map.js";
5
+ /**
6
+ * Creates a reactive query API for messages.
7
+ */
8
+ export function createMessageLintReportsQuery(messages, config, installedMessageLintRules, resolvedModules) {
9
+ // @ts-expect-error
10
+ const index = new ReactiveMap();
11
+ createEffect(() => {
12
+ const msgs = messages();
13
+ const conf = config();
14
+ const modules = resolvedModules();
15
+ if (msgs && conf && modules) {
16
+ // console.log("new calculation")
17
+ // index.clear()
18
+ for (const message of msgs) {
19
+ // TODO: only lint changed messages and update arrays selectively
20
+ lintSingleMessage({
21
+ rules: modules.messageLintRules,
22
+ ruleSettings: conf.settings,
23
+ ruleLevels: Object.fromEntries(installedMessageLintRules().map((rule) => [rule.meta.id, rule.lintLevel])),
24
+ sourceLanguageTag: conf.sourceLanguageTag,
25
+ languageTags: conf.languageTags,
26
+ messages: msgs,
27
+ message: message,
28
+ }).then((report) => {
29
+ if (report.errors.length === 0 &&
30
+ JSON.stringify(index.get(message.id)) !== JSON.stringify(report.data)) {
31
+ index.set(message.id, report.data || []);
32
+ }
33
+ });
34
+ }
35
+ }
36
+ });
37
+ const get = (args) => {
38
+ return structuredClone(index.get(args.where.messageId));
39
+ };
40
+ return {
41
+ getAll: createSubscribable(() => {
42
+ return structuredClone([...index.values()].flat().length === 0 ? [] : [...index.values()].flat());
43
+ }),
44
+ get: Object.assign(get, {
45
+ subscribe: (args, callback) => createSubscribable(() => get(args)).subscribe(callback),
46
+ }),
47
+ };
48
+ }
@@ -0,0 +1,7 @@
1
+ import type { Message } from "@inlang/message";
2
+ import type { InlangProject } from "./api.js";
3
+ /**
4
+ * Creates a reactive query API for messages.
5
+ */
6
+ export declare function createMessagesQuery(messages: () => Array<Message>): InlangProject["query"]["messages"];
7
+ //# sourceMappingURL=createMessagesQuery.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createMessagesQuery.d.ts","sourceRoot":"","sources":["../src/createMessagesQuery.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAA;AAI9C,OAAO,KAAK,EAAE,aAAa,EAAmB,MAAM,UAAU,CAAA;AAE9D;;GAEG;AACH,wBAAgB,mBAAmB,CAClC,QAAQ,EAAE,MAAM,KAAK,CAAC,OAAO,CAAC,GAC5B,aAAa,CAAC,OAAO,CAAC,CAAC,UAAU,CAAC,CAoDpC"}
@@ -0,0 +1,57 @@
1
+ import { ReactiveMap } from "./reactivity/map.js";
2
+ import { createEffect } from "./reactivity/solid.js";
3
+ import { createSubscribable } from "./openInlangProject.js";
4
+ /**
5
+ * Creates a reactive query API for messages.
6
+ */
7
+ export function createMessagesQuery(messages) {
8
+ // @ts-expect-error
9
+ const index = new ReactiveMap();
10
+ createEffect(() => {
11
+ index.clear();
12
+ for (const message of messages()) {
13
+ index.set(message.id, message);
14
+ }
15
+ });
16
+ const get = (args) => index.get(args.where.id);
17
+ return {
18
+ create: ({ data }) => {
19
+ if (index.has(data.id))
20
+ return false;
21
+ index.set(data.id, data);
22
+ return true;
23
+ },
24
+ get: Object.assign(get, {
25
+ subscribe: (args, callback) => createSubscribable(() => get(args)).subscribe(callback),
26
+ }),
27
+ includedMessageIds: createSubscribable(() => {
28
+ return [...index.keys()];
29
+ }),
30
+ getAll: createSubscribable(() => {
31
+ return [...index.values()];
32
+ }),
33
+ update: ({ where, data }) => {
34
+ const message = index.get(where.id);
35
+ if (message === undefined)
36
+ return false;
37
+ index.set(where.id, { ...message, ...data });
38
+ return true;
39
+ },
40
+ upsert: ({ where, data }) => {
41
+ const message = index.get(where.id);
42
+ if (message === undefined) {
43
+ index.set(where.id, data);
44
+ }
45
+ else {
46
+ index.set(where.id, { ...message, ...data });
47
+ }
48
+ return true;
49
+ },
50
+ delete: ({ where }) => {
51
+ if (!index.has(where.id))
52
+ return false;
53
+ index.delete(where.id);
54
+ return true;
55
+ },
56
+ };
57
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=createMessagesQuery.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createMessagesQuery.test.d.ts","sourceRoot":"","sources":["../src/createMessagesQuery.test.ts"],"names":[],"mappings":""}