@inlang/sdk 0.35.4 → 0.35.6

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 (111) hide show
  1. package/dist/adapter/solidAdapter.test.js +1 -1
  2. package/dist/api.d.ts +2 -13
  3. package/dist/api.d.ts.map +1 -1
  4. package/dist/createMessagesQuery.d.ts.map +1 -1
  5. package/dist/createMessagesQuery.js +68 -82
  6. package/dist/createNewProject.test.js +1 -3
  7. package/dist/loadProject.d.ts.map +1 -1
  8. package/dist/loadProject.js +67 -32
  9. package/dist/loadProject.test.js +6 -2
  10. package/dist/persistence/batchedIO.d.ts +11 -0
  11. package/dist/persistence/batchedIO.d.ts.map +1 -0
  12. package/dist/persistence/batchedIO.js +49 -0
  13. package/dist/persistence/batchedIO.test.d.ts +2 -0
  14. package/dist/persistence/batchedIO.test.d.ts.map +1 -0
  15. package/dist/persistence/batchedIO.test.js +56 -0
  16. package/dist/persistence/filelock/acquireFileLock.d.ts.map +1 -1
  17. package/dist/persistence/filelock/acquireFileLock.js +3 -1
  18. package/dist/persistence/filelock/releaseLock.d.ts.map +1 -1
  19. package/dist/persistence/filelock/releaseLock.js +2 -1
  20. package/dist/persistence/store.d.ts +107 -0
  21. package/dist/persistence/store.d.ts.map +1 -0
  22. package/dist/persistence/store.js +99 -0
  23. package/dist/persistence/store.test.d.ts +2 -0
  24. package/dist/persistence/store.test.d.ts.map +1 -0
  25. package/dist/persistence/store.test.js +79 -0
  26. package/dist/persistence/storeApi.d.ts +22 -0
  27. package/dist/persistence/storeApi.d.ts.map +1 -0
  28. package/dist/persistence/storeApi.js +1 -0
  29. package/dist/reactivity/solid.test.js +1 -6
  30. package/dist/resolve-modules/plugins/resolvePlugins.d.ts.map +1 -1
  31. package/dist/resolve-modules/plugins/resolvePlugins.js +3 -10
  32. package/dist/test-utilities/sleep.d.ts +4 -0
  33. package/dist/test-utilities/sleep.d.ts.map +1 -0
  34. package/dist/test-utilities/sleep.js +9 -0
  35. package/dist/v2/helper.d.ts +131 -0
  36. package/dist/v2/helper.d.ts.map +1 -0
  37. package/dist/v2/helper.js +75 -0
  38. package/dist/v2/helper.test.d.ts +2 -0
  39. package/dist/v2/helper.test.d.ts.map +1 -0
  40. package/dist/v2/{createMessageBundle.test.js → helper.test.js} +1 -1
  41. package/dist/v2/index.d.ts +2 -0
  42. package/dist/v2/index.d.ts.map +1 -1
  43. package/dist/v2/index.js +2 -1
  44. package/dist/v2/mocks/index.d.ts +3 -0
  45. package/dist/v2/mocks/index.d.ts.map +1 -0
  46. package/dist/v2/mocks/index.js +2 -0
  47. package/dist/v2/mocks/multipleMatcher/bundle.d.ts +3 -0
  48. package/dist/v2/mocks/multipleMatcher/bundle.d.ts.map +1 -0
  49. package/dist/v2/mocks/multipleMatcher/bundle.js +194 -0
  50. package/dist/v2/mocks/multipleMatcher/bundle.test.d.ts +2 -0
  51. package/dist/v2/mocks/multipleMatcher/bundle.test.d.ts.map +1 -0
  52. package/dist/v2/mocks/multipleMatcher/bundle.test.js +10 -0
  53. package/dist/v2/mocks/plural/bundle.d.ts +1 -1
  54. package/dist/v2/mocks/plural/bundle.d.ts.map +1 -1
  55. package/dist/v2/mocks/plural/bundle.js +1 -1
  56. package/dist/v2/mocks/plural/bundle.test.js +6 -6
  57. package/dist/v2/shim.d.ts +12 -0
  58. package/dist/v2/shim.d.ts.map +1 -0
  59. package/dist/v2/shim.js +151 -0
  60. package/dist/v2/shim.test.d.ts +2 -0
  61. package/dist/v2/shim.test.d.ts.map +1 -0
  62. package/dist/v2/shim.test.js +49 -0
  63. package/dist/v2/stubQueryApi.d.ts +9 -0
  64. package/dist/v2/stubQueryApi.d.ts.map +1 -0
  65. package/dist/v2/stubQueryApi.js +38 -0
  66. package/dist/v2/types.d.ts +110 -0
  67. package/dist/v2/types.d.ts.map +1 -1
  68. package/dist/v2/types.js +9 -0
  69. package/package.json +9 -8
  70. package/src/adapter/solidAdapter.test.ts +1 -1
  71. package/src/api.ts +2 -13
  72. package/src/createMessagesQuery.ts +80 -99
  73. package/src/createNewProject.test.ts +1 -4
  74. package/src/loadProject.test.ts +6 -2
  75. package/src/loadProject.ts +86 -45
  76. package/src/persistence/batchedIO.test.ts +63 -0
  77. package/src/persistence/batchedIO.ts +64 -0
  78. package/src/persistence/filelock/acquireFileLock.ts +5 -2
  79. package/src/persistence/filelock/releaseLock.ts +2 -1
  80. package/src/persistence/store.test.ts +102 -0
  81. package/src/persistence/store.ts +119 -0
  82. package/src/persistence/storeApi.ts +19 -0
  83. package/src/reactivity/solid.test.ts +1 -8
  84. package/src/resolve-modules/plugins/resolvePlugins.ts +4 -13
  85. package/src/test-utilities/sleep.ts +11 -0
  86. package/src/v2/{createMessageBundle.test.ts → helper.test.ts} +1 -1
  87. package/src/v2/helper.ts +98 -0
  88. package/src/v2/index.ts +2 -0
  89. package/src/v2/mocks/index.ts +2 -0
  90. package/src/v2/mocks/multipleMatcher/bundle.test.ts +11 -0
  91. package/src/v2/mocks/multipleMatcher/bundle.ts +196 -0
  92. package/src/v2/mocks/plural/bundle.test.ts +6 -6
  93. package/src/v2/mocks/plural/bundle.ts +1 -1
  94. package/src/v2/shim.test.ts +56 -0
  95. package/src/v2/shim.ts +173 -0
  96. package/src/v2/stubQueryApi.ts +43 -0
  97. package/src/v2/types.ts +17 -0
  98. package/dist/persistence/plugin.d.ts +0 -31
  99. package/dist/persistence/plugin.d.ts.map +0 -1
  100. package/dist/persistence/plugin.js +0 -42
  101. package/dist/persistence/plugin.test.d.ts +0 -2
  102. package/dist/persistence/plugin.test.d.ts.map +0 -1
  103. package/dist/persistence/plugin.test.js +0 -49
  104. package/dist/v2/createMessageBundle.d.ts +0 -25
  105. package/dist/v2/createMessageBundle.d.ts.map +0 -1
  106. package/dist/v2/createMessageBundle.js +0 -36
  107. package/dist/v2/createMessageBundle.test.d.ts +0 -2
  108. package/dist/v2/createMessageBundle.test.d.ts.map +0 -1
  109. package/src/persistence/plugin.test.ts +0 -60
  110. package/src/persistence/plugin.ts +0 -56
  111. package/src/v2/createMessageBundle.ts +0 -43
@@ -1,6 +1,6 @@
1
1
  import type { MessageBundle } from "../../types.js"
2
2
 
3
- export const bundle: MessageBundle = {
3
+ export const pluralBundle: MessageBundle = {
4
4
  id: "mock_bundle_human_id",
5
5
  alias: {
6
6
  default: "mock_bundle_alias",
@@ -0,0 +1,56 @@
1
+ import { test, expect } from "vitest"
2
+ import * as V2 from "./types.js"
3
+ import * as V1 from "@inlang/message"
4
+ import { createMessageBundle, createMessage } from "./helper.js"
5
+ import { toV1Message, fromV1Message } from "./shim.js"
6
+ import { Value } from "@sinclair/typebox/value"
7
+
8
+ const bundle = createMessageBundle({
9
+ id: "hello_world",
10
+ messages: [
11
+ createMessage({ locale: "en", text: "Hello World!" }),
12
+ createMessage({ locale: "de", text: "Hallo Welt!" }),
13
+ ],
14
+ })
15
+
16
+ test("toV1Message and fromV1Message", () => {
17
+ expect(Value.Check(V2.MessageBundle, bundle)).toBe(true)
18
+
19
+ const v1Message: unknown = toV1Message(bundle)
20
+ expect(Value.Check(V1.Message, v1Message)).toBe(true)
21
+
22
+ expect(v1Message).toEqual({
23
+ id: "hello_world",
24
+ alias: {},
25
+ variants: [
26
+ {
27
+ languageTag: "en",
28
+ match: [],
29
+ pattern: [
30
+ {
31
+ type: "Text",
32
+ value: "Hello World!",
33
+ },
34
+ ],
35
+ },
36
+ {
37
+ languageTag: "de",
38
+ match: [],
39
+ pattern: [
40
+ {
41
+ type: "Text",
42
+ value: "Hallo Welt!",
43
+ },
44
+ ],
45
+ },
46
+ ],
47
+ selectors: [],
48
+ })
49
+
50
+ const v2MessageBundle: unknown = fromV1Message(v1Message as V1.Message)
51
+ expect(Value.Check(V2.MessageBundle, v2MessageBundle)).toBe(true)
52
+
53
+ expect(v2MessageBundle).toEqual(bundle)
54
+ })
55
+
56
+ test.todo("with variable references", () => {})
package/src/v2/shim.ts ADDED
@@ -0,0 +1,173 @@
1
+ /**
2
+ * Convert between v1 Message and v2 MessageBundle formats.
3
+ * Code adapted from https://github.com/opral/monorepo/pull/2655 legacy.ts
4
+ */
5
+
6
+ import * as V2 from "./types.js"
7
+ import * as V1 from "@inlang/message"
8
+
9
+ /**
10
+ * @throws If the message cannot be represented in the v1 format
11
+ */
12
+ export function toV1Message(bundle: V2.MessageBundle): V1.Message {
13
+ const variants: V1.Variant[] = []
14
+ const selectorNames = new Set<string>()
15
+
16
+ for (const message of bundle.messages) {
17
+ // collect all selector names
18
+ for (const selector of message.selectors.map(toV1Expression)) {
19
+ selectorNames.add(selector.name)
20
+ }
21
+
22
+ // collect all variants
23
+ for (const variant of message.variants) {
24
+ variants.push({
25
+ languageTag: message.locale,
26
+ match: variant.match,
27
+ pattern: toV1Pattern(variant.pattern),
28
+ })
29
+ }
30
+ }
31
+
32
+ const selectors: V1.Expression[] = [...selectorNames].map((name) => ({
33
+ type: "VariableReference",
34
+ name,
35
+ }))
36
+
37
+ return {
38
+ id: bundle.id,
39
+ alias: bundle.alias,
40
+ variants,
41
+ selectors,
42
+ }
43
+ }
44
+
45
+ /**
46
+ * @throws If the pattern cannot be represented in the v1 format
47
+ */
48
+ function toV1Pattern(pattern: V2.Pattern): V1.Pattern {
49
+ return pattern.map((element) => {
50
+ switch (element.type) {
51
+ case "text": {
52
+ return {
53
+ type: "Text",
54
+ value: element.value,
55
+ }
56
+ }
57
+
58
+ case "expression": {
59
+ return toV1Expression(element)
60
+ }
61
+
62
+ default: {
63
+ throw new Error(`Unsupported pattern element type`)
64
+ }
65
+ }
66
+ })
67
+ }
68
+
69
+ function toV1Expression(expression: V2.Expression): V1.Expression {
70
+ if (expression.annotation !== undefined)
71
+ throw new Error("Cannot convert an expression with an annotation to the v1 format")
72
+
73
+ if (expression.arg.type !== "variable") {
74
+ throw new Error("Can only convert variable references to the v1 format")
75
+ }
76
+
77
+ return {
78
+ type: "VariableReference",
79
+ name: expression.arg.name,
80
+ }
81
+ }
82
+
83
+ export function fromV1Message(v1Message: V1.Message): V2.MessageBundle {
84
+ const languages = dedup(v1Message.variants.map((variant) => variant.languageTag))
85
+
86
+ const messages: V2.Message[] = languages.map((language): V2.Message => {
87
+ //All variants that will be part of this message
88
+ const v1Variants = v1Message.variants.filter((variant) => variant.languageTag === language)
89
+
90
+ //find all selector names
91
+ const selectorNames = new Set<string>()
92
+ for (const v1Selector of v1Message.selectors) {
93
+ selectorNames.add(v1Selector.name)
94
+ }
95
+ const selectors: V2.Expression[] = [...selectorNames].map((name) => ({
96
+ type: "expression",
97
+ annotation: undefined,
98
+ arg: {
99
+ type: "variable",
100
+ name: name,
101
+ },
102
+ }))
103
+
104
+ //The set of variables that need to be defined - Certainly includes the selectors
105
+ const variableNames = new Set<string>(selectorNames)
106
+ const variants: V2.Variant[] = []
107
+ for (const v1Variant of v1Variants) {
108
+ for (const element of v1Variant.pattern) {
109
+ if (element.type === "VariableReference") {
110
+ variableNames.add(element.name)
111
+ }
112
+ }
113
+
114
+ variants.push({
115
+ match: v1Variant.match,
116
+ pattern: fromV1Pattern(v1Variant.pattern),
117
+ })
118
+ }
119
+
120
+ //Create an input declaration for each variable and selector we need
121
+ const declarations: V2.Declaration[] = [...variableNames].map((name) => ({
122
+ type: "input",
123
+ name,
124
+ value: {
125
+ type: "expression",
126
+ annotation: undefined,
127
+ arg: {
128
+ type: "variable",
129
+ name,
130
+ },
131
+ },
132
+ }))
133
+
134
+ return {
135
+ locale: language,
136
+ declarations,
137
+ selectors,
138
+ variants,
139
+ }
140
+ })
141
+
142
+ return {
143
+ id: v1Message.id,
144
+ alias: v1Message.alias,
145
+ messages,
146
+ }
147
+ }
148
+
149
+ function fromV1Pattern(pattern: V1.Pattern): V2.Pattern {
150
+ return pattern.map((element) => {
151
+ switch (element.type) {
152
+ case "Text": {
153
+ return {
154
+ type: "text",
155
+ value: element.value,
156
+ }
157
+ }
158
+ case "VariableReference":
159
+ return {
160
+ type: "expression",
161
+ arg: {
162
+ type: "variable",
163
+ name: element.name,
164
+ },
165
+ }
166
+ }
167
+ })
168
+ }
169
+
170
+ /**
171
+ * Dedups an array by converting it to a set and back
172
+ */
173
+ const dedup = <T extends Array<unknown>>(arr: T): T => [...new Set(arr)] as T
@@ -0,0 +1,43 @@
1
+ import type { MessageQueryApi, MessageLintReportsQueryApi } from "../api.js"
2
+
3
+ /**
4
+ * noop implementation of the message query api for use with experimental.persistence = true.
5
+ * NOTE: If we implemented v2 shims for the old api we could use existing tests and make apps
6
+ * backwards compatible.
7
+ */
8
+ export const stubMessagesQuery: MessageQueryApi = {
9
+ create: () => false,
10
+ // @ts-expect-error
11
+ get: subscribable(() => undefined),
12
+ // @ts-expect-error
13
+ getByDefaultAlias: subscribable(() => undefined),
14
+ // @ts-expect-error
15
+ includedMessageIds: subscribable(() => []),
16
+ // @ts-expect-error
17
+ getAll: subscribable(() => []),
18
+ update: () => false,
19
+ upsert: () => {},
20
+ delete: () => false,
21
+ setDelegate: () => {},
22
+ }
23
+
24
+ export const stubMessageLintReportsQuery: MessageLintReportsQueryApi = {
25
+ // @ts-expect-error
26
+ get: subscribable(() => []),
27
+ // @ts-expect-error
28
+ getAll: settleable(subscribable(() => [])),
29
+ }
30
+
31
+ // eslint-disable-next-line @typescript-eslint/ban-types
32
+ function subscribable(fn: Function) {
33
+ return Object.assign(fn, {
34
+ subscribe: () => {},
35
+ })
36
+ }
37
+
38
+ // eslint-disable-next-line @typescript-eslint/ban-types
39
+ function settleable(fn: Function) {
40
+ return Object.assign(fn, {
41
+ settled: async () => {},
42
+ })
43
+ }
package/src/v2/types.ts CHANGED
@@ -140,3 +140,20 @@ export const MessageBundle = Type.Object({
140
140
  alias: Type.Record(Type.String(), Type.String()),
141
141
  messages: Type.Array(Message),
142
142
  })
143
+
144
+ /**
145
+ * A MessageSlot is a placeholder for a message with a locale.
146
+ * This is useful to avoid merge conflicts when translations are added.
147
+ */
148
+ export type MessageSlot = Static<typeof MessageSlot>
149
+ export const MessageSlot = Type.Object({
150
+ locale: LanguageTag,
151
+ slot: Type.Literal(true),
152
+ })
153
+
154
+ export type MessageBundleWithSlots = Static<typeof MessageBundleWithSlots>
155
+ export const MessageBundleWithSlots = Type.Object({
156
+ id: Type.String(),
157
+ alias: Type.Record(Type.String(), Type.String()),
158
+ messages: Type.Array(Type.Union([Message, MessageSlot])),
159
+ })
@@ -1,31 +0,0 @@
1
- import type { ProjectSettings, Message } from "@inlang/sdk";
2
- import { type NodeishFilesystem } from "@lix-js/fs";
3
- export declare const pluginId = "plugin.sdk.persistence";
4
- export declare function loadMessages(args: {
5
- settings: ProjectSettings;
6
- nodeishFs: NodeishFilesystem;
7
- }): Promise<{
8
- id: string;
9
- alias: Record<string, string>;
10
- selectors: {
11
- type: "VariableReference";
12
- name: string;
13
- }[];
14
- variants: {
15
- languageTag: string;
16
- match: string[];
17
- pattern: ({
18
- type: "Text";
19
- value: string;
20
- } | {
21
- type: "VariableReference";
22
- name: string;
23
- })[];
24
- }[];
25
- }[]>;
26
- export declare function saveMessages(args: {
27
- settings: ProjectSettings;
28
- nodeishFs: NodeishFilesystem;
29
- messages: Message[];
30
- }): Promise<void>;
31
- //# sourceMappingURL=plugin.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../src/persistence/plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,aAAa,CAAA;AAC3D,OAAO,EAAc,KAAK,iBAAiB,EAAE,MAAM,YAAY,CAAA;AAM/D,eAAO,MAAM,QAAQ,2BAA2B,CAAA;AAEhD,wBAAsB,YAAY,CAAC,IAAI,EAAE;IACxC,QAAQ,EAAE,eAAe,CAAA;IACzB,SAAS,EAAE,iBAAiB,CAAA;CAC5B;;;;;;;;;;;;;;;;;;KAeA;AAED,wBAAsB,YAAY,CAAC,IAAI,EAAE;IACxC,QAAQ,EAAE,eAAe,CAAA;IACzB,SAAS,EAAE,iBAAiB,CAAA;IAC5B,QAAQ,EAAE,OAAO,EAAE,CAAA;CACnB,iBAcA"}
@@ -1,42 +0,0 @@
1
- import { getDirname } from "@lix-js/fs";
2
- import { normalizeMessage } from "../storage/helper.js";
3
- import _debug from "debug";
4
- const debug = _debug("sdk:persistence");
5
- export const pluginId = "plugin.sdk.persistence";
6
- export async function loadMessages(args) {
7
- let result = [];
8
- const pathPattern = args.settings[pluginId]?.pathPattern;
9
- debug("loadMessages", pathPattern);
10
- try {
11
- const file = await args.nodeishFs.readFile(pathPattern, { encoding: "utf-8" });
12
- result = JSON.parse(file);
13
- }
14
- catch (error) {
15
- if (error?.code !== "ENOENT") {
16
- debug("loadMessages", error);
17
- throw error;
18
- }
19
- }
20
- return result;
21
- }
22
- export async function saveMessages(args) {
23
- const pathPattern = args.settings[pluginId]?.pathPattern;
24
- debug("saveMessages", pathPattern);
25
- try {
26
- await createDirectoryIfNotExits(getDirname(pathPattern), args.nodeishFs);
27
- await args.nodeishFs.writeFile(pathPattern,
28
- // 2 spaces indentation
29
- JSON.stringify(args.messages.map(normalizeMessage), undefined, 2));
30
- }
31
- catch (error) {
32
- debug("saveMessages", error);
33
- }
34
- }
35
- async function createDirectoryIfNotExits(path, nodeishFs) {
36
- try {
37
- await nodeishFs.mkdir(path, { recursive: true });
38
- }
39
- catch {
40
- // assume that the directory already exists
41
- }
42
- }
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=plugin.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"plugin.test.d.ts","sourceRoot":"","sources":["../../src/persistence/plugin.test.ts"],"names":[],"mappings":""}
@@ -1,49 +0,0 @@
1
- import { test, expect } from "vitest";
2
- import { createMessage, createNodeishMemoryFs } from "../test-utilities/index.js";
3
- import { normalizeMessage } from "../storage/helper.js";
4
- import { pluginId } from "./plugin.js";
5
- const mockMessages = [
6
- createMessage("first_message", {
7
- en: "If this fails I will be sad",
8
- }),
9
- createMessage("second_message", {
10
- en: "Let's see if this works",
11
- de: "Mal sehen ob das funktioniert",
12
- }),
13
- ];
14
- // the test ensures:
15
- // - messages can be loaded
16
- // - messages can be saved
17
- // - after loading and saving messages, the state is the same as before (roundtrip)
18
- test("roundtrip (saving/loading messages)", async () => {
19
- const { loadMessages, saveMessages } = await import("./plugin.js");
20
- const fs = createNodeishMemoryFs();
21
- const projectDir = "/test/project.inlang";
22
- const pathPattern = projectDir + "/messages.json";
23
- const persistedMessages = JSON.stringify(mockMessages.map(normalizeMessage), undefined, 2);
24
- const settings = {
25
- sourceLanguageTag: "en",
26
- languageTags: ["en", "de"],
27
- modules: [],
28
- [pluginId]: { pathPattern },
29
- };
30
- await fs.mkdir(projectDir, { recursive: true });
31
- await fs.writeFile(pathPattern, persistedMessages);
32
- const firstMessageLoad = await loadMessages({
33
- settings,
34
- nodeishFs: fs,
35
- });
36
- expect(firstMessageLoad).toStrictEqual(mockMessages);
37
- await saveMessages({
38
- settings,
39
- nodeishFs: fs,
40
- messages: firstMessageLoad,
41
- });
42
- const afterRoundtrip = await fs.readFile(pathPattern, { encoding: "utf-8" });
43
- expect(afterRoundtrip).toStrictEqual(persistedMessages);
44
- const messagesAfterRoundtrip = await loadMessages({
45
- settings,
46
- nodeishFs: fs,
47
- });
48
- expect(messagesAfterRoundtrip).toStrictEqual(firstMessageLoad);
49
- });
@@ -1,25 +0,0 @@
1
- import { LanguageTag, MessageBundle, Message } from "./types.js";
2
- /**
3
- * create v2 MessageBundle
4
- * @example createMessageBundle({
5
- * id: "greeting",
6
- * messages: [
7
- * createMessage({locale: "en", text: "Hello world!"})
8
- * createMessage({locale: "de", text: "Hallo Welt!"})
9
- * ]
10
- * })
11
- */
12
- export declare function createMessageBundle(args: {
13
- id: string;
14
- messages: Message[];
15
- alias?: MessageBundle["alias"];
16
- }): MessageBundle;
17
- /**
18
- * create v2 Messsage AST with text-only pattern
19
- * @example createMessage({locale: "en", text: "Hello world"})
20
- */
21
- export declare function createMessage(args: {
22
- locale: LanguageTag;
23
- text: string;
24
- }): Message;
25
- //# sourceMappingURL=createMessageBundle.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"createMessageBundle.d.ts","sourceRoot":"","sources":["../../src/v2/createMessageBundle.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,OAAO,EAAQ,MAAM,YAAY,CAAA;AAEtE;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE;IACzC,EAAE,EAAE,MAAM,CAAA;IACV,QAAQ,EAAE,OAAO,EAAE,CAAA;IACnB,KAAK,CAAC,EAAE,aAAa,CAAC,OAAO,CAAC,CAAA;CAC9B,GAAG,aAAa,CAMhB;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE;IAAE,MAAM,EAAE,WAAW,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAOlF"}
@@ -1,36 +0,0 @@
1
- import { LanguageTag, MessageBundle, Message, Text } from "./types.js";
2
- /**
3
- * create v2 MessageBundle
4
- * @example createMessageBundle({
5
- * id: "greeting",
6
- * messages: [
7
- * createMessage({locale: "en", text: "Hello world!"})
8
- * createMessage({locale: "de", text: "Hallo Welt!"})
9
- * ]
10
- * })
11
- */
12
- export function createMessageBundle(args) {
13
- return {
14
- id: args.id,
15
- alias: args.alias ?? {},
16
- messages: args.messages,
17
- };
18
- }
19
- /**
20
- * create v2 Messsage AST with text-only pattern
21
- * @example createMessage({locale: "en", text: "Hello world"})
22
- */
23
- export function createMessage(args) {
24
- return {
25
- locale: args.locale,
26
- declarations: [],
27
- selectors: [],
28
- variants: [{ match: [], pattern: [toTextElement(args.text ?? "")] }],
29
- };
30
- }
31
- function toTextElement(text) {
32
- return {
33
- type: "text",
34
- value: text,
35
- };
36
- }
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=createMessageBundle.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"createMessageBundle.test.d.ts","sourceRoot":"","sources":["../../src/v2/createMessageBundle.test.ts"],"names":[],"mappings":""}
@@ -1,60 +0,0 @@
1
- import { test, expect } from "vitest"
2
- import { createMessage, createNodeishMemoryFs } from "../test-utilities/index.js"
3
- import { normalizeMessage } from "../storage/helper.js"
4
- import { pluginId } from "./plugin.js"
5
-
6
- const mockMessages = [
7
- createMessage("first_message", {
8
- en: "If this fails I will be sad",
9
- }),
10
- createMessage("second_message", {
11
- en: "Let's see if this works",
12
- de: "Mal sehen ob das funktioniert",
13
- }),
14
- ]
15
-
16
- // the test ensures:
17
- // - messages can be loaded
18
- // - messages can be saved
19
- // - after loading and saving messages, the state is the same as before (roundtrip)
20
- test("roundtrip (saving/loading messages)", async () => {
21
- const { loadMessages, saveMessages } = await import("./plugin.js")
22
- const fs = createNodeishMemoryFs()
23
- const projectDir = "/test/project.inlang"
24
- const pathPattern = projectDir + "/messages.json"
25
- const persistedMessages = JSON.stringify(mockMessages.map(normalizeMessage), undefined, 2)
26
-
27
- const settings = {
28
- sourceLanguageTag: "en",
29
- languageTags: ["en", "de"],
30
- modules: [],
31
- [pluginId]: { pathPattern },
32
- }
33
-
34
- await fs.mkdir(projectDir, { recursive: true })
35
- await fs.writeFile(pathPattern, persistedMessages)
36
-
37
- const firstMessageLoad = await loadMessages({
38
- settings,
39
- nodeishFs: fs,
40
- })
41
-
42
- expect(firstMessageLoad).toStrictEqual(mockMessages)
43
-
44
- await saveMessages({
45
- settings,
46
- nodeishFs: fs,
47
- messages: firstMessageLoad,
48
- })
49
-
50
- const afterRoundtrip = await fs.readFile(pathPattern, { encoding: "utf-8" })
51
-
52
- expect(afterRoundtrip).toStrictEqual(persistedMessages)
53
-
54
- const messagesAfterRoundtrip = await loadMessages({
55
- settings,
56
- nodeishFs: fs,
57
- })
58
-
59
- expect(messagesAfterRoundtrip).toStrictEqual(firstMessageLoad)
60
- })
@@ -1,56 +0,0 @@
1
- import type { ProjectSettings, Message } from "@inlang/sdk"
2
- import { getDirname, type NodeishFilesystem } from "@lix-js/fs"
3
- import { normalizeMessage } from "../storage/helper.js"
4
-
5
- import _debug from "debug"
6
- const debug = _debug("sdk:persistence")
7
-
8
- export const pluginId = "plugin.sdk.persistence"
9
-
10
- export async function loadMessages(args: {
11
- settings: ProjectSettings
12
- nodeishFs: NodeishFilesystem
13
- }) {
14
- let result: Message[] = []
15
- const pathPattern = args.settings[pluginId]?.pathPattern as string
16
-
17
- debug("loadMessages", pathPattern)
18
- try {
19
- const file = await args.nodeishFs.readFile(pathPattern, { encoding: "utf-8" })
20
- result = JSON.parse(file)
21
- } catch (error) {
22
- if ((error as any)?.code !== "ENOENT") {
23
- debug("loadMessages", error)
24
- throw error
25
- }
26
- }
27
- return result
28
- }
29
-
30
- export async function saveMessages(args: {
31
- settings: ProjectSettings
32
- nodeishFs: NodeishFilesystem
33
- messages: Message[]
34
- }) {
35
- const pathPattern = args.settings[pluginId]?.pathPattern as string
36
-
37
- debug("saveMessages", pathPattern)
38
- try {
39
- await createDirectoryIfNotExits(getDirname(pathPattern), args.nodeishFs)
40
- await args.nodeishFs.writeFile(
41
- pathPattern,
42
- // 2 spaces indentation
43
- JSON.stringify(args.messages.map(normalizeMessage), undefined, 2)
44
- )
45
- } catch (error) {
46
- debug("saveMessages", error)
47
- }
48
- }
49
-
50
- async function createDirectoryIfNotExits(path: string, nodeishFs: NodeishFilesystem) {
51
- try {
52
- await nodeishFs.mkdir(path, { recursive: true })
53
- } catch {
54
- // assume that the directory already exists
55
- }
56
- }
@@ -1,43 +0,0 @@
1
- import { LanguageTag, MessageBundle, Message, Text } from "./types.js"
2
-
3
- /**
4
- * create v2 MessageBundle
5
- * @example createMessageBundle({
6
- * id: "greeting",
7
- * messages: [
8
- * createMessage({locale: "en", text: "Hello world!"})
9
- * createMessage({locale: "de", text: "Hallo Welt!"})
10
- * ]
11
- * })
12
- */
13
- export function createMessageBundle(args: {
14
- id: string
15
- messages: Message[]
16
- alias?: MessageBundle["alias"]
17
- }): MessageBundle {
18
- return {
19
- id: args.id,
20
- alias: args.alias ?? {},
21
- messages: args.messages,
22
- }
23
- }
24
-
25
- /**
26
- * create v2 Messsage AST with text-only pattern
27
- * @example createMessage({locale: "en", text: "Hello world"})
28
- */
29
- export function createMessage(args: { locale: LanguageTag; text: string }): Message {
30
- return {
31
- locale: args.locale,
32
- declarations: [],
33
- selectors: [],
34
- variants: [{ match: [], pattern: [toTextElement(args.text ?? "")] }],
35
- }
36
- }
37
-
38
- function toTextElement(text: string): Text {
39
- return {
40
- type: "text",
41
- value: text,
42
- }
43
- }