@inlang/sdk 2.0.0-beta.5 → 2.0.0-beta.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.
- package/dist/plugin/importPlugins.test.js +2 -3
- package/dist/plugin/importPlugins.test.js.map +1 -1
- package/dist/project/loadProjectFromDirectory.d.ts +2 -1
- package/dist/project/loadProjectFromDirectory.d.ts.map +1 -1
- package/dist/project/loadProjectFromDirectory.js +34 -49
- package/dist/project/loadProjectFromDirectory.js.map +1 -1
- package/dist/project/loadProjectFromDirectory.test.js +59 -3
- package/dist/project/loadProjectFromDirectory.test.js.map +1 -1
- package/dist/services/env-variables/index.js +3 -3
- package/dist/services/env-variables/index.js.map +1 -1
- package/package.json +1 -1
- package/src/plugin/importPlugins.test.ts +0 -1
- package/src/project/loadProjectFromDirectory.test.ts +69 -1
- package/src/project/loadProjectFromDirectory.ts +40 -94
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="
|
|
2
|
+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="d56eea49-1483-5227-ae80-1f01de298ace")}catch(e){}}();
|
|
3
3
|
import { test, expect, vi } from "vitest";
|
|
4
4
|
import { importPlugins } from "./importPlugins.js";
|
|
5
5
|
import { PluginImportError } from "./errors.js";
|
|
@@ -21,7 +21,6 @@ test("it should preprocess a plugin", async () => {
|
|
|
21
21
|
return moduleText.replace("mock", "preprocessed");
|
|
22
22
|
},
|
|
23
23
|
});
|
|
24
|
-
expect(global.fetch).toHaveBeenCalledTimes(1);
|
|
25
24
|
expect(result.plugins.length).toBe(1);
|
|
26
25
|
expect(result.errors.length).toBe(0);
|
|
27
26
|
expect(result.plugins[0]?.key).toBe("preprocessed");
|
|
@@ -92,4 +91,4 @@ test("cache should work", async () => {
|
|
|
92
91
|
expect(result.plugins[0]?.key).toBe("mock");
|
|
93
92
|
});
|
|
94
93
|
//# sourceMappingURL=importPlugins.test.js.map
|
|
95
|
-
//# debugId=
|
|
94
|
+
//# debugId=d56eea49-1483-5227-ae80-1f01de298ace
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"importPlugins.test.js","sources":["plugin/importPlugins.test.ts"],"sourceRoot":"/","sourcesContent":["import { test, expect, vi } from \"vitest\";\nimport { importPlugins } from \"./importPlugins.js\";\nimport { PluginImportError } from \"./errors.js\";\nimport { newLixFile, openLixInMemory } from \"@lix-js/sdk\";\n\ntest(\"it should preprocess a plugin\", async () => {\n\tglobal.fetch = vi.fn().mockResolvedValue({\n\t\tok: true,\n\t\ttext: vi.fn().mockResolvedValue(\"export default { key: 'mock' }\"),\n\t});\n\n\tconst lix = await openLixInMemory({ blob: await newLixFile() });\n\tconst result = await importPlugins({\n\t\tlix,\n\t\tsettings: {\n\t\t\tbaseLocale: \"en\",\n\t\t\tlocales: [\"en\"],\n\t\t\tmodules: [\"https://mock.com/module.js\"],\n\t\t},\n\t\tpreprocessPluginBeforeImport: async (moduleText) => {\n\t\t\treturn moduleText.replace(\"mock\", \"preprocessed\");\n\t\t},\n\t});\n\n\texpect(
|
|
1
|
+
{"version":3,"file":"importPlugins.test.js","sources":["plugin/importPlugins.test.ts"],"sourceRoot":"/","sourcesContent":["import { test, expect, vi } from \"vitest\";\nimport { importPlugins } from \"./importPlugins.js\";\nimport { PluginImportError } from \"./errors.js\";\nimport { newLixFile, openLixInMemory } from \"@lix-js/sdk\";\n\ntest(\"it should preprocess a plugin\", async () => {\n\tglobal.fetch = vi.fn().mockResolvedValue({\n\t\tok: true,\n\t\ttext: vi.fn().mockResolvedValue(\"export default { key: 'mock' }\"),\n\t});\n\n\tconst lix = await openLixInMemory({ blob: await newLixFile() });\n\tconst result = await importPlugins({\n\t\tlix,\n\t\tsettings: {\n\t\t\tbaseLocale: \"en\",\n\t\t\tlocales: [\"en\"],\n\t\t\tmodules: [\"https://mock.com/module.js\"],\n\t\t},\n\t\tpreprocessPluginBeforeImport: async (moduleText) => {\n\t\t\treturn moduleText.replace(\"mock\", \"preprocessed\");\n\t\t},\n\t});\n\n\texpect(result.plugins.length).toBe(1);\n\texpect(result.errors.length).toBe(0);\n\texpect(result.plugins[0]?.key).toBe(\"preprocessed\");\n});\n\ntest(\"if a fetch fails, a plugin import error is expected\", async () => {\n\tglobal.fetch = vi.fn().mockResolvedValue({\n\t\tok: false,\n\t\tstatusText: \"HTTP 404\",\n\t});\n\tconst lix = await openLixInMemory({ blob: await newLixFile() });\n\n\tconst result = await importPlugins({\n\t\tlix,\n\t\tsettings: {\n\t\t\tbaseLocale: \"en\",\n\t\t\tlocales: [\"en\"],\n\t\t\tmodules: [\"https://mock.com/module.js\"],\n\t\t},\n\t});\n\n\texpect(global.fetch).toHaveBeenCalledTimes(1);\n\texpect(result.plugins.length).toBe(0);\n\texpect(result.errors.length).toBe(1);\n\texpect(result.errors[0]).toBeInstanceOf(PluginImportError);\n});\n\ntest(\"it should filter message lint rules for legacy reasons\", async () => {\n\tglobal.fetch = vi.fn().mockResolvedValue({\n\t\tok: true,\n\t\ttext: vi\n\t\t\t.fn()\n\t\t\t.mockResolvedValue(\"export default { id: 'messageLintRule.something' }\"),\n\t});\n\n\tconst lix = await openLixInMemory({ blob: await newLixFile() });\n\n\tconst result = await importPlugins({\n\t\tlix,\n\t\tsettings: {\n\t\t\tbaseLocale: \"en\",\n\t\t\tlocales: [\"en\"],\n\t\t\tmodules: [\"https://mock.com/module.js\"],\n\t\t},\n\t});\n\n\texpect(result.plugins.length).toBe(0);\n\texpect(result.errors.length).toBe(0);\n});\n\n// more tests are found in cache.test.ts\ntest(\"cache should work\", async () => {\n\tglobal.fetch = vi.fn().mockResolvedValue({\n\t\tok: false,\n\t});\n\n\tconst mockModulePath = \"https://mock.com/module.js\";\n\tconst mockModuleCachePath = \"/cache/plugins/31i1etp0l413h\";\n\n\tconst lix = await openLixInMemory({ blob: await newLixFile() });\n\n\tawait lix.db\n\t\t.insertInto(\"file\")\n\t\t.values({\n\t\t\tpath: mockModuleCachePath,\n\t\t\tdata: new TextEncoder().encode(\"export default { key: 'mock' }\"),\n\t\t})\n\t\t.execute();\n\n\tconst result = await importPlugins({\n\t\tlix,\n\t\tsettings: {\n\t\t\tbaseLocale: \"en\",\n\t\t\tlocales: [\"en\"],\n\t\t\tmodules: [mockModulePath],\n\t\t},\n\t});\n\n\texpect(result.errors).lengthOf(0);\n\texpect(result.plugins).lengthOf(1);\n\texpect(result.plugins[0]?.key).toBe(\"mock\");\n});\n"],"names":[],"mappings":"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","debug_id":"d56eea49-1483-5227-ae80-1f01de298ace"}
|
|
@@ -3,6 +3,7 @@ import { type Lix } from "@lix-js/sdk";
|
|
|
3
3
|
import fs from "node:fs";
|
|
4
4
|
import type { InlangPlugin, NodeFsPromisesSubsetLegacy } from "../plugin/schema.js";
|
|
5
5
|
import type { ProjectSettings } from "../json-schema/settings.js";
|
|
6
|
+
import type { ImportFile } from "./api.js";
|
|
6
7
|
/**
|
|
7
8
|
* Loads a project from a directory.
|
|
8
9
|
*
|
|
@@ -32,7 +33,7 @@ export declare function loadProjectFromDirectory(args: {
|
|
|
32
33
|
lix: Lix;
|
|
33
34
|
importFiles: (args: {
|
|
34
35
|
pluginKey: InlangPlugin["key"];
|
|
35
|
-
files:
|
|
36
|
+
files: ImportFile[];
|
|
36
37
|
}) => Promise<void>;
|
|
37
38
|
exportFiles: (args: {
|
|
38
39
|
pluginKey: InlangPlugin["key"];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loadProjectFromDirectory.d.ts","sourceRoot":"/","sources":["project/loadProjectFromDirectory.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAAE,KAAK,GAAG,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"loadProjectFromDirectory.d.ts","sourceRoot":"/","sources":["project/loadProjectFromDirectory.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAAE,KAAK,GAAG,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,MAAM,SAAS,CAAC;AAEzB,OAAO,KAAK,EACX,YAAY,EACZ,0BAA0B,EAC1B,MAAM,qBAAqB,CAAC;AAE7B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAIlE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAE3C;;;;;GAKG;AACH,wBAAsB,wBAAwB,CAC7C,IAAI,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,OAAO,EAAE,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAClE,UAAU,CAAC,OAAO,mBAAmB,CAAC,CAAC,CAAC,CAAC,EACzC,MAAM,CACN;;;;;;;;;;;;;;;;;;;;;;;;;;GA0HD;AA2dD,qBAAa,yBAA0B,SAAQ,KAAK;gBACvC,MAAM,EAAE,MAAM;CAM1B;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,iBAAiB,CAChC,EAAE,EAAE,0BAA0B,EAC9B,WAAW,EAAE,MAAM,GACjB,0BAA0B,CAgB5B;AAED;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,UAWxE;AAED,qBAAa,uBAAwB,SAAQ,KAAK;IACjD,IAAI,EAAE,MAAM,CAAC;gBAED,IAAI,EAAE;QAAE,KAAK,EAAE,KAAK,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE;CAMhD"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="
|
|
2
|
+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="effafa39-b15a-55ff-a980-555f1b5eaed5")}catch(e){}}();
|
|
3
3
|
import { newProject } from "./newProject.js";
|
|
4
4
|
import { loadProjectInMemory } from "./loadProjectInMemory.js";
|
|
5
5
|
import {} from "@lix-js/sdk";
|
|
@@ -43,55 +43,34 @@ export async function loadProjectFromDirectory(args) {
|
|
|
43
43
|
lix: project.lix,
|
|
44
44
|
syncInterval: args.syncInterval,
|
|
45
45
|
});
|
|
46
|
-
const
|
|
46
|
+
const allPlugins = await project.plugins.get();
|
|
47
|
+
const { loadSavePlugins, importExportPlugins } = categorizePlugins(allPlugins);
|
|
47
48
|
// TODO i guess we should move this validation logic into sdk2/src/project/loadProject.ts
|
|
48
49
|
// Two scenarios could arise:
|
|
49
50
|
// 1. set settings is called from an app - it should detect and reject the setting of settings -> app need to be able to validate before calling set
|
|
50
51
|
// 2. the settings file loaded from disc here is corrupted -> user has to fix the file on disc
|
|
51
|
-
if (
|
|
52
|
+
if (loadSavePlugins.length > 1) {
|
|
52
53
|
throw new Error("Max one loadMessages (found: " +
|
|
53
|
-
|
|
54
|
+
loadSavePlugins.length +
|
|
54
55
|
") and one saveMessages plugins (found: " +
|
|
55
|
-
|
|
56
|
+
loadSavePlugins.length +
|
|
56
57
|
") are allowed ");
|
|
57
58
|
}
|
|
58
59
|
const importedResourceFileErrors = [];
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
throw new Error("Plugins for loadMessages (found: " +
|
|
62
|
-
loadMessagesPlugins.length +
|
|
63
|
-
") and saveMessages plugins (found: " +
|
|
64
|
-
saveMessagesPlugins.length +
|
|
65
|
-
") must not coexist with import (found: " +
|
|
66
|
-
importPlugins.length +
|
|
67
|
-
") or export (found: " +
|
|
68
|
-
exportPlugins.length +
|
|
69
|
-
") ");
|
|
70
|
-
}
|
|
71
|
-
else if (loadMessagesPlugins.length > 1 || saveMessagesPlugins.length > 1) {
|
|
72
|
-
throw new Error("Max one loadMessages (found: " +
|
|
73
|
-
loadMessagesPlugins.length +
|
|
74
|
-
") and one saveMessages plugins (found: " +
|
|
75
|
-
saveMessagesPlugins.length +
|
|
76
|
-
") are allowed ");
|
|
77
|
-
}
|
|
78
|
-
else if (importPlugins[0]) {
|
|
79
|
-
const importer = importPlugins[0];
|
|
60
|
+
// import files from local fs
|
|
61
|
+
for (const plugin of importExportPlugins) {
|
|
80
62
|
const files = [];
|
|
81
|
-
if (
|
|
82
|
-
const toBeImportedFiles = await
|
|
63
|
+
if (plugin.toBeImportedFiles) {
|
|
64
|
+
const toBeImportedFiles = await plugin.toBeImportedFiles({
|
|
83
65
|
settings: await project.settings.get(),
|
|
84
66
|
});
|
|
85
67
|
for (const toBeImported of toBeImportedFiles) {
|
|
86
68
|
const absolute = absolutePathFromProject(args.path, toBeImported.path);
|
|
87
69
|
try {
|
|
88
70
|
const data = await args.fs.promises.readFile(absolute);
|
|
89
|
-
const name = nodePath.basename(toBeImported.path);
|
|
90
71
|
files.push({
|
|
91
|
-
name,
|
|
92
72
|
locale: toBeImported.locale,
|
|
93
73
|
content: data,
|
|
94
|
-
pluginKey: importer.key,
|
|
95
74
|
toBeImportedFilesMetadata: toBeImported.metadata,
|
|
96
75
|
});
|
|
97
76
|
}
|
|
@@ -108,18 +87,17 @@ export async function loadProjectFromDirectory(args) {
|
|
|
108
87
|
}
|
|
109
88
|
}
|
|
110
89
|
await project.importFiles({
|
|
111
|
-
pluginKey:
|
|
112
|
-
files
|
|
90
|
+
pluginKey: plugin.key,
|
|
91
|
+
files,
|
|
113
92
|
});
|
|
114
93
|
}
|
|
115
|
-
|
|
116
|
-
// TODO create resource files from loadMessageFn call - to poll?
|
|
94
|
+
for (const plugin of loadSavePlugins) {
|
|
117
95
|
await loadLegacyMessages({
|
|
118
96
|
project,
|
|
97
|
+
pluginKey: plugin.key ?? plugin.id,
|
|
98
|
+
loadMessagesFn: plugin.loadMessages,
|
|
119
99
|
projectPath: args.path,
|
|
120
100
|
fs: args.fs,
|
|
121
|
-
pluginKey: loadMessagesPlugins[0].key ?? loadMessagesPlugins[0].id,
|
|
122
|
-
loadMessagesFn: loadMessagesPlugins[0].loadMessages,
|
|
123
101
|
});
|
|
124
102
|
}
|
|
125
103
|
return {
|
|
@@ -466,18 +444,25 @@ async function upsertFileInLix(args, path, data) {
|
|
|
466
444
|
.onConflict((oc) => oc.column("path").doUpdateSet({ data: new Uint8Array(data) }))
|
|
467
445
|
.execute();
|
|
468
446
|
}
|
|
469
|
-
|
|
447
|
+
/**
|
|
448
|
+
* Filters legacy load and save messages plugins.
|
|
449
|
+
*
|
|
450
|
+
* Legacy plugins are plugins that implement loadMessages and saveMessages but not importFiles and exportFiles.
|
|
451
|
+
*/
|
|
470
452
|
function categorizePlugins(plugins) {
|
|
471
|
-
const
|
|
472
|
-
const
|
|
473
|
-
const
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
453
|
+
const loadSavePlugins = [];
|
|
454
|
+
const importExportPlugins = [];
|
|
455
|
+
for (const plugin of plugins) {
|
|
456
|
+
if (plugin.loadMessages &&
|
|
457
|
+
plugin.saveMessages &&
|
|
458
|
+
!(plugin.importFiles && plugin.exportFiles)) {
|
|
459
|
+
loadSavePlugins.push(plugin);
|
|
460
|
+
}
|
|
461
|
+
else if (plugin.importFiles || plugin.exportFiles) {
|
|
462
|
+
importExportPlugins.push(plugin);
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
return { loadSavePlugins, importExportPlugins };
|
|
481
466
|
}
|
|
482
467
|
/**
|
|
483
468
|
* Imports local plugins for backwards compatibility.
|
|
@@ -581,4 +566,4 @@ export class ResourceFileImportError extends Error {
|
|
|
581
566
|
}
|
|
582
567
|
}
|
|
583
568
|
//# sourceMappingURL=loadProjectFromDirectory.js.map
|
|
584
|
-
//# debugId=
|
|
569
|
+
//# debugId=effafa39-b15a-55ff-a980-555f1b5eaed5
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loadProjectFromDirectory.js","sources":["project/loadProjectFromDirectory.ts"],"sourceRoot":"/","sourcesContent":["import { newProject } from \"./newProject.js\";\nimport { loadProjectInMemory } from \"./loadProjectInMemory.js\";\nimport { type Lix } from \"@lix-js/sdk\";\n\nimport fs from \"node:fs\";\n\nimport nodePath from \"node:path\";\nimport type {\n\tInlangPlugin,\n\tNodeFsPromisesSubsetLegacy,\n} from \"../plugin/schema.js\";\nimport { fromMessageV1 } from \"../json-schema/old-v1-message/fromMessageV1.js\";\nimport type { ProjectSettings } from \"../json-schema/settings.js\";\nimport type { PreprocessPluginBeforeImportFunction } from \"../plugin/importPlugins.js\";\nimport { PluginImportError } from \"../plugin/errors.js\";\nimport { upsertBundleNestedMatchByProperties } from \"../import-export/upsertBundleNestedMatchByProperties.js\";\n\n/**\n * Loads a project from a directory.\n *\n * Main use case are dev tools that want to load a project from a directory\n * that is stored in git.\n */\nexport async function loadProjectFromDirectory(\n\targs: { path: string; fs: typeof fs; syncInterval?: number } & Omit<\n\t\tParameters<typeof loadProjectInMemory>[0],\n\t\t\"blob\"\n\t>\n) {\n\tconst settingsPath = nodePath.join(args.path, \"settings.json\");\n\tconst settings = JSON.parse(\n\t\tawait args.fs.promises.readFile(settingsPath, \"utf8\")\n\t) as ProjectSettings;\n\n\tconst localImport = await importLocalPlugins({\n\t\tfs: args.fs,\n\t\tsettings,\n\t\tpath: args.path,\n\t});\n\n\tconst providePluginsWithLocalPlugins = [\n\t\t...(args.providePlugins ?? []),\n\t\t...localImport.locallyImportedPlugins,\n\t];\n\n\t// TODO call tempProject.lix.settled() to wait for the new settings file, and remove reload of the proejct as soon as reactive settings has landed\n\t// NOTE: we need to ensure two things:\n\t// 1. settled needs to include the changes from the copyFiles call\n\t// 2. the changes created from the copyFiles call need to be realized and lead to a signal on the settings\n\tconst project = await loadProjectInMemory({\n\t\t...args,\n\t\tprovidePlugins: providePluginsWithLocalPlugins,\n\t\tblob: await newProject({\n\t\t\tsettings,\n\t\t}),\n\t});\n\n\tawait syncLixFsFiles({\n\t\tfs: args.fs,\n\t\tpath: args.path,\n\t\tlix: project.lix,\n\t\tsyncInterval: args.syncInterval,\n\t});\n\n\tconst {\n\t\tloadMessagesPlugins,\n\t\tsaveMessagesPlugins,\n\t\timportPlugins,\n\t\texportPlugins,\n\t} = categorizePlugins(await project.plugins.get());\n\n\t// TODO i guess we should move this validation logic into sdk2/src/project/loadProject.ts\n\t// Two scenarios could arise:\n\t// 1. set settings is called from an app - it should detect and reject the setting of settings -> app need to be able to validate before calling set\n\t// 2. the settings file loaded from disc here is corrupted -> user has to fix the file on disc\n\tif (loadMessagesPlugins.length > 1 || saveMessagesPlugins.length > 1) {\n\t\tthrow new Error(\n\t\t\t\"Max one loadMessages (found: \" +\n\t\t\t\tloadMessagesPlugins.length +\n\t\t\t\t\") and one saveMessages plugins (found: \" +\n\t\t\t\tsaveMessagesPlugins.length +\n\t\t\t\t\") are allowed \"\n\t\t);\n\t}\n\tconst importedResourceFileErrors: Error[] = [];\n\n\tif (\n\t\t(loadMessagesPlugins.length > 0 || saveMessagesPlugins.length > 0) &&\n\t\t(exportPlugins.length > 0 || importPlugins.length > 0)\n\t) {\n\t\tthrow new Error(\n\t\t\t\"Plugins for loadMessages (found: \" +\n\t\t\t\tloadMessagesPlugins.length +\n\t\t\t\t\") and saveMessages plugins (found: \" +\n\t\t\t\tsaveMessagesPlugins.length +\n\t\t\t\t\") must not coexist with import (found: \" +\n\t\t\t\timportPlugins.length +\n\t\t\t\t\") or export (found: \" +\n\t\t\t\texportPlugins.length +\n\t\t\t\t\") \"\n\t\t);\n\t} else if (loadMessagesPlugins.length > 1 || saveMessagesPlugins.length > 1) {\n\t\tthrow new Error(\n\t\t\t\"Max one loadMessages (found: \" +\n\t\t\t\tloadMessagesPlugins.length +\n\t\t\t\t\") and one saveMessages plugins (found: \" +\n\t\t\t\tsaveMessagesPlugins.length +\n\t\t\t\t\") are allowed \"\n\t\t);\n\t} else if (importPlugins[0]) {\n\t\tconst importer = importPlugins[0];\n\t\tconst files = [];\n\n\t\tif (importer.toBeImportedFiles) {\n\t\t\tconst toBeImportedFiles = await importer.toBeImportedFiles({\n\t\t\t\tsettings: await project.settings.get(),\n\t\t\t});\n\t\t\tfor (const toBeImported of toBeImportedFiles) {\n\t\t\t\tconst absolute = absolutePathFromProject(args.path, toBeImported.path);\n\t\t\t\ttry {\n\t\t\t\t\tconst data = await args.fs.promises.readFile(absolute);\n\t\t\t\t\tconst name = nodePath.basename(toBeImported.path);\n\t\t\t\t\tfiles.push({\n\t\t\t\t\t\tname,\n\t\t\t\t\t\tlocale: toBeImported.locale,\n\t\t\t\t\t\tcontent: data,\n\t\t\t\t\t\tpluginKey: importer.key,\n\t\t\t\t\t\ttoBeImportedFilesMetadata: toBeImported.metadata,\n\t\t\t\t\t});\n\t\t\t\t} catch (e) {\n\t\t\t\t\t// https://github.com/opral/inlang-sdk/issues/202\n\t\t\t\t\tif ((e as any)?.code === \"ENOENT\") {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\timportedResourceFileErrors.push(\n\t\t\t\t\t\tnew ResourceFileImportError({\n\t\t\t\t\t\t\tcause: e as Error,\n\t\t\t\t\t\t\tpath: toBeImported.path,\n\t\t\t\t\t\t})\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tawait project.importFiles({\n\t\t\tpluginKey: importer.key,\n\t\t\tfiles: files as any,\n\t\t});\n\t} else if (loadMessagesPlugins[0] !== undefined) {\n\t\t// TODO create resource files from loadMessageFn call - to poll?\n\t\tawait loadLegacyMessages({\n\t\t\tproject,\n\t\t\tprojectPath: args.path,\n\t\t\tfs: args.fs,\n\t\t\tpluginKey: loadMessagesPlugins[0].key ?? loadMessagesPlugins[0].id,\n\t\t\tloadMessagesFn: loadMessagesPlugins[0].loadMessages,\n\t\t});\n\t}\n\n\treturn {\n\t\t...project,\n\t\terrors: {\n\t\t\tget: async () => {\n\t\t\t\treturn [...localImport.errors, ...importedResourceFileErrors];\n\t\t\t},\n\t\t\t// subscribe: (\n\t\t\t// \tcallback: Parameters<InlangProject[\"errors\"][\"subscribe\"]>[0]\n\t\t\t// ) => {\n\t\t\t// \treturn project.errors.subscribe((value) => {\n\t\t\t// \t\tcallback([\n\t\t\t// \t\t\t...withLocallyImportedPluginWarning(value),\n\t\t\t// \t\t\t...localImport.errors,\n\t\t\t// \t\t\t...importedResourceFileErrors,\n\t\t\t// \t\t]);\n\t\t\t// \t});\n\t\t\t// },\n\t\t},\n\t};\n}\n\nasync function loadLegacyMessages(args: {\n\tproject: Awaited<ReturnType<typeof loadProjectInMemory>>;\n\tpluginKey: NonNullable<InlangPlugin[\"key\"] | InlangPlugin[\"id\"]>;\n\tloadMessagesFn: Required<InlangPlugin>[\"loadMessages\"];\n\tprojectPath: string;\n\tfs: typeof fs;\n}) {\n\tconst loadedLegacyMessages = await args.loadMessagesFn({\n\t\tsettings: await args.project.settings.get(),\n\t\t// @ts-expect-error - type mismatch\n\t\tnodeishFs: withAbsolutePaths(args.fs.promises, args.projectPath),\n\t});\n\tconst upsertQueries = [];\n\n\tfor (const legacyMessage of loadedLegacyMessages) {\n\t\tconst messageBundle = fromMessageV1(legacyMessage);\n\n\t\tupsertQueries.push(\n\t\t\tupsertBundleNestedMatchByProperties(args.project.db, messageBundle)\n\t\t);\n\t}\n\n\treturn await Promise.all(upsertQueries);\n}\n\ntype FsFileState = Record<\n\tstring,\n\t{\n\t\t/*mtime: number, hash: string, */ content: ArrayBuffer;\n\t\tstate: \"known\" | \"unknown\" | \"updated\" | \"gone\";\n\t}\n>;\n\nfunction arrayBuffersEqual(a: ArrayBuffer, b: ArrayBuffer) {\n\tif (a.byteLength !== b.byteLength) return false;\n\n\t// Create views for byte-by-byte comparison\n\tconst view1 = new Uint8Array(a);\n\tconst view2 = new Uint8Array(b);\n\n\t// Compare each byte\n\tfor (const [i, element] of view1.entries()) {\n\t\tif (element !== view2[i]) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\treturn true;\n}\n\n/**\n * Watches a directory and copies files into lix, keeping them in sync.\n */\nasync function syncLixFsFiles(args: {\n\tfs: typeof fs;\n\tpath: string;\n\tlix: Lix;\n\tsyncInterval?: number;\n}) {\n\t// NOTE this function is async - while it runs 100% sync in the naiv implementation - we may want to change to an async version to optimize\n\tasync function checkFsStateRecursive(\n\t\tdirPath: string,\n\t\tcurrentState: FsFileState\n\t) {\n\t\tconst entries = args.fs.readdirSync(dirPath, { withFileTypes: true });\n\n\t\tfor (const entry of entries) {\n\t\t\tconst fullPath = nodePath.join(dirPath, entry.name);\n\t\t\tif (entry.isDirectory()) {\n\t\t\t\tcheckFsStateRecursive(fullPath, currentState);\n\t\t\t} else {\n\t\t\t\t// NOTE we could start with comparing the mdate and skip file read completely...\n\t\t\t\tconst data = args.fs.readFileSync(fullPath) as unknown as ArrayBuffer;\n\n\t\t\t\tconst relativePath = \"/\" + nodePath.relative(args.path, fullPath);\n\n\t\t\t\tif (!currentState[relativePath]) {\n\t\t\t\t\tcurrentState[relativePath] = {\n\t\t\t\t\t\tcontent: data,\n\t\t\t\t\t\tstate: \"unknown\",\n\t\t\t\t\t};\n\t\t\t\t} else {\n\t\t\t\t\tif (arrayBuffersEqual(currentState[relativePath].content, data)) {\n\t\t\t\t\t\tcurrentState[relativePath].state = \"known\";\n\t\t\t\t\t} else {\n\t\t\t\t\t\tcurrentState[relativePath].state = \"updated\";\n\t\t\t\t\t\tcurrentState[relativePath].content = data;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tasync function checkLixState(currentLixState: FsFileState) {\n\t\t// go through all files in lix and check there state\n\t\tconst filesInLix = await args.lix.db\n\t\t\t.selectFrom(\"file\")\n\t\t\t.where(\"path\", \"not like\", \"%db.sqlite\")\n\t\t\t.selectAll()\n\t\t\t.execute();\n\n\t\tfor (const fileInLix of filesInLix) {\n\t\t\tconst currentStateOfFileInLix = currentLixState[fileInLix.path];\n\t\t\t// NOTE we could start with comparing the mdate and skip file read completely...\n\t\t\tif (!currentStateOfFileInLix) {\n\t\t\t\tcurrentLixState[fileInLix.path] = {\n\t\t\t\t\tcontent: new Uint8Array(fileInLix.data).buffer,\n\t\t\t\t\tstate: \"unknown\",\n\t\t\t\t};\n\t\t\t} else {\n\t\t\t\tif (\n\t\t\t\t\tarrayBuffersEqual(\n\t\t\t\t\t\tcurrentStateOfFileInLix.content,\n\t\t\t\t\t\tfileInLix.data.buffer as ArrayBuffer\n\t\t\t\t\t)\n\t\t\t\t) {\n\t\t\t\t\tcurrentStateOfFileInLix.state = \"known\";\n\t\t\t\t} else {\n\t\t\t\t\tcurrentStateOfFileInLix.state = \"updated\";\n\t\t\t\t\tcurrentStateOfFileInLix.content = fileInLix.data\n\t\t\t\t\t\t.buffer as ArrayBuffer;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tasync function syncUpFsAndLixFiles(statesToSync: {\n\t\tfsFileStates: FsFileState;\n\t\tlixFileStates: FsFileState;\n\t}) {\n\t\t// for (const file of Object.keys(statesToSync.fsFileStates)) {\n\t\t// \tif (file.includes(\"gitignore\"))\n\t\t// \t\tconsole.log(\n\t\t// \t\t\t\"fsFileStates : \" +\n\t\t// \t\t\t\tfile +\n\t\t// \t\t\t\t\" fs \" +\n\t\t// \t\t\t\tstatesToSync.fsFileStates[file]?.state +\n\t\t// \t\t\t\t\" lix \" +\n\t\t// \t\t\t\tstatesToSync.lixFileStates[file]?.state\n\t\t// \t\t);\n\t\t// }\n\n\t\t// Sync cases:\n\t\t// fs - no state for file | fs - unkonwn | fs - known | fs - updated | fs - gone\n\t\t// lix - no state for file \tNOTHING\t(1)\t | ADD TO LIX(2) | ERROR (3) | ERROR (4) | ERROR (5)\n\t\t// lix - unknown\t\t\t\t\tADD TO FS (6) | USE FS VER.(7) | ERROR (8) | CASE (9) | CASE (10)\n\t\t// lix - known ERROR (11) | ERROR (12) | NOTHING(13) | ERROR (14) | ERROR (15)\n\t\t// lix - updated\t\t\t\t\tERROR (16) | ERROR (17) | USE LIX (18) | CASE (19) | CASE (20)\n\t\t// lix - gone \t\t\t\t\t\tERROR (21) | ERROR (22) | DELETE FS (23)| CASE (24) | CASE (25)\n\n\t\t// TODO check export import from saveFileToDirectory\n\n\t\tfor (const [path, fsState] of Object.entries(statesToSync.fsFileStates)) {\n\t\t\t// no state for file in LIX\n\t\t\tif (!statesToSync.lixFileStates[path]) {\n\t\t\t\tif (fsState.state === \"unknown\") {\n\t\t\t\t\t// ADD TO LIX(2)\n\t\t\t\t\tawait upsertFileInLix(args, path, fsState.content);\n\t\t\t\t\tstatesToSync.lixFileStates[path] = {\n\t\t\t\t\t\tstate: \"known\",\n\t\t\t\t\t\tcontent: fsState.content,\n\t\t\t\t\t};\n\t\t\t\t\tfsState.state = \"known\";\n\t\t\t\t} else {\n\t\t\t\t\t// ERROR (3), ERROR (4), ERROR (5)\n\t\t\t\t\t// The file does not exist in lix but its state differs from unknown?\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\"Illeagal lix<->fs sync state. The file [\" +\n\t\t\t\t\t\t\tpath +\n\t\t\t\t\t\t\t\"] that was \" +\n\t\t\t\t\t\t\tfsState.state +\n\t\t\t\t\t\t\t\" on disc did not exit in lix\"\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tconst lixState = statesToSync.lixFileStates[path];\n\t\t\t\tif (fsState.state === \"unknown\") {\n\t\t\t\t\tif (lixState.state === \"unknown\") {\n\t\t\t\t\t\tif (arrayBuffersEqual(lixState.content, fsState.content)) {\n\t\t\t\t\t\t\tlixState.state = \"known\";\n\t\t\t\t\t\t\tfsState.state = \"known\";\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tawait upsertFileInLix(args, path, fsState.content);\n\t\t\t\t\t\t\tlixState.content = fsState.content;\n\t\t\t\t\t\t\tlixState.state = \"known\";\n\t\t\t\t\t\t\tfsState.state = \"known\";\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// ERROR 12, 17, 22\n\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t\"Illeagal lix<->fs sync state. The file [\" +\n\t\t\t\t\t\t\t\tpath +\n\t\t\t\t\t\t\t\t\"] that was \" +\n\t\t\t\t\t\t\t\tfsState.state +\n\t\t\t\t\t\t\t\t\" but did exist in lix already\"\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t} else if (fsState.state === \"known\") {\n\t\t\t\t\tif (lixState.state === \"known\") {\n\t\t\t\t\t\t// NO OP - NOTHING(13)\n\t\t\t\t\t} else if (lixState.state === \"updated\") {\n\t\t\t\t\t\t// USE LIX (18)\n\t\t\t\t\t\targs.fs.writeFileSync(\n\t\t\t\t\t\t\t// TODO check platform dependent folder separator\n\t\t\t\t\t\t\targs.path + path,\n\t\t\t\t\t\t\tBuffer.from(lixState.content)\n\t\t\t\t\t\t);\n\t\t\t\t\t\tfsState.content = lixState.content;\n\t\t\t\t\t\tfsState.state = \"known\";\n\t\t\t\t\t\tlixState.state = \"known\";\n\t\t\t\t\t} else if (lixState.state === \"gone\") {\n\t\t\t\t\t\t// DELETE FS (23)\n\t\t\t\t\t\targs.fs.unlinkSync(args.path + path);\n\t\t\t\t\t\tfsState.state = \"gone\";\n\t\t\t\t\t\tlixState.state = \"gone\";\n\t\t\t\t\t}\n\t\t\t\t} else if (fsState.state === \"updated\") {\n\t\t\t\t\tif (lixState.state === \"unknown\") {\n\t\t\t\t\t\t// TODO A file was added to lix while a known file from fs was updated?\n\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t\"Illeagal lix<->fs sync state. The file [\" +\n\t\t\t\t\t\t\t\tpath +\n\t\t\t\t\t\t\t\t\"] that was \" +\n\t\t\t\t\t\t\t\tfsState.state +\n\t\t\t\t\t\t\t\t\" but it was not known by lix yet?\"\n\t\t\t\t\t\t);\n\t\t\t\t\t} else if (lixState.state === \"known\") {\n\t\t\t\t\t\tawait upsertFileInLix(args, path, fsState.content);\n\t\t\t\t\t\tlixState.content = fsState.content;\n\n\t\t\t\t\t\tfsState.state = \"known\";\n\t\t\t\t\t} else if (lixState.state === \"updated\") {\n\t\t\t\t\t\t// seems like we saw an update on the file in fs while some changes on lix have not been reached fs? FS -> Winns?\n\t\t\t\t\t\tconsole.warn(\n\t\t\t\t\t\t\t\"seems like we saw an update on the file \" +\n\t\t\t\t\t\t\t\tpath +\n\t\t\t\t\t\t\t\t\" in fs while some changes on lix have not been reached fs? FS -> Winns?\"\n\t\t\t\t\t\t);\n\t\t\t\t\t\tawait upsertFileInLix(args, path, fsState.content);\n\t\t\t\t\t\tlixState.content = fsState.content;\n\t\t\t\t\t\tlixState.state = \"known\";\n\t\t\t\t\t\tfsState.state = \"known\";\n\t\t\t\t\t} else if (lixState.state === \"gone\") {\n\t\t\t\t\t\tconsole.warn(\n\t\t\t\t\t\t\t\"seems like we saw an delete in lix while some changes on fs have not been reached fs? FS -> Winns?\"\n\t\t\t\t\t\t);\n\t\t\t\t\t\t// TODO update the lix state\n\t\t\t\t\t\tlixState.content = fsState.content;\n\t\t\t\t\t\tlixState.state = \"known\";\n\t\t\t\t\t\tfsState.state = \"known\";\n\t\t\t\t\t}\n\t\t\t\t} else if (fsState.state === \"gone\") {\n\t\t\t\t\tif (lixState.state === \"unknown\") {\n\t\t\t\t\t\t// TODO A file was added to lix while a known file from fs was removed?\n\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t\"Illeagal lix<->fs sync state. The file [\" +\n\t\t\t\t\t\t\t\tpath +\n\t\t\t\t\t\t\t\t\"] that was \" +\n\t\t\t\t\t\t\t\tfsState.state +\n\t\t\t\t\t\t\t\t\" but it was not known by lix yet?\"\n\t\t\t\t\t\t);\n\t\t\t\t\t} else if (lixState.state === \"known\") {\n\t\t\t\t\t\t// file is in known state with lix - means we have only changes on the fs - easy\n\t\t\t\t\t\tawait args.lix.db\n\t\t\t\t\t\t\t.deleteFrom(\"file\")\n\t\t\t\t\t\t\t.where(\"path\", \"=\", path)\n\t\t\t\t\t\t\t.execute();\n\t\t\t\t\t\t// NOTE: states where both are gone will get removed in the lix state loop\n\t\t\t\t\t\tlixState.state = \"gone\";\n\t\t\t\t\t} else if (lixState.state === \"updated\") {\n\t\t\t\t\t\t// seems like we saw an update on the file in fs while some changes on lix have not been reached fs? FS -> Winns?\n\t\t\t\t\t\tconsole.warn(\n\t\t\t\t\t\t\t\"seems like we saw an update on the file in fs while some changes on lix have not been reached fs? FS -> Winns?\"\n\t\t\t\t\t\t);\n\t\t\t\t\t\tawait args.lix.db\n\t\t\t\t\t\t\t.deleteFrom(\"file\")\n\t\t\t\t\t\t\t.where(\"path\", \"=\", path)\n\t\t\t\t\t\t\t.execute();\n\t\t\t\t\t\t// NOTE: states where both are gone will get removed in the lix state loop\n\t\t\t\t\t\tlixState.state = \"gone\";\n\t\t\t\t\t\tfsState.state = \"gone\";\n\t\t\t\t\t} else if (lixState.state === \"gone\") {\n\t\t\t\t\t\tconsole.warn(\n\t\t\t\t\t\t\t\"seems like we saw an delete in lix while we have a delete in lix simultaniously?\"\n\t\t\t\t\t\t);\n\t\t\t\t\t\tlixState.state = \"gone\";\n\t\t\t\t\t\tfsState.state = \"gone\";\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tfor (const [path, lixState] of Object.entries(statesToSync.lixFileStates)) {\n\t\t\t// no state for file in fs\n\t\t\tif (!statesToSync.fsFileStates[path]) {\n\t\t\t\tif (lixState.state == \"unknown\") {\n\t\t\t\t\t// ADD TO FS (6)\n\t\t\t\t\t// create directory if not exists\n\t\t\t\t\targs.fs.mkdirSync(nodePath.dirname(nodePath.join(args.path, path)), {\n\t\t\t\t\t\trecursive: true,\n\t\t\t\t\t});\n\t\t\t\t\t// write file\n\t\t\t\t\targs.fs.writeFileSync(\n\t\t\t\t\t\tnodePath.join(args.path, path),\n\t\t\t\t\t\tBuffer.from(lixState.content)\n\t\t\t\t\t);\n\t\t\t\t\tstatesToSync.fsFileStates[path] = {\n\t\t\t\t\t\tstate: \"known\",\n\t\t\t\t\t\tcontent: lixState.content,\n\t\t\t\t\t};\n\t\t\t\t} else {\n\t\t\t\t\t// ERROR (11) 16 21\n\t\t\t\t\t// The file does not exist on fs but its state differs from unknown?\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\"Illeagal lix<->fs sync state. The file [\" +\n\t\t\t\t\t\t\tpath +\n\t\t\t\t\t\t\t\"] that was in the state\" +\n\t\t\t\t\t\t\tlixState.state +\n\t\t\t\t\t\t\t\" for lix did not exist on disk\"\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (\n\t\t\t\t\tlixState.state === \"gone\" &&\n\t\t\t\t\tstatesToSync.fsFileStates[path].state === \"gone\"\n\t\t\t\t) {\n\t\t\t\t\tdelete statesToSync.lixFileStates[path];\n\t\t\t\t\tdelete statesToSync.fsFileStates[path];\n\t\t\t\t} else if (lixState.state !== statesToSync.fsFileStates[path].state) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\"At this stage both states should be in sync lix state \" +\n\t\t\t\t\t\t\tlixState.state +\n\t\t\t\t\t\t\t\" fs state \" +\n\t\t\t\t\t\t\tstatesToSync.fsFileStates[path].state\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tasync function syncFiles(\n\t\tdirPath: string,\n\t\tfileStates: {\n\t\t\tlixFileStates: FsFileState;\n\t\t\tfsFileStates: FsFileState;\n\t\t},\n\t\tinterval?: number\n\t) {\n\t\t// mark all states as removed - checkFsStateRecursive will update those that exist on the disc correspondingly\n\t\tfor (const fsState of Object.values(fileStates.fsFileStates)) {\n\t\t\tfsState.state = \"gone\";\n\t\t}\n\n\t\t// mark all states as removed - checkFsStateRecursive will update those that exist on the disc correspondingly\n\t\tfor (const lixState of Object.values(fileStates.lixFileStates)) {\n\t\t\tlixState.state = \"gone\";\n\t\t}\n\n\t\t// read states from disc - detect changes\n\t\tawait checkFsStateRecursive(dirPath, fileStates.fsFileStates);\n\n\t\t// read states form lix - detect changes\n\t\tawait checkLixState(fileStates.lixFileStates);\n\n\t\t// sync fs<->lix\n\t\tawait syncUpFsAndLixFiles(fileStates);\n\n\t\tif (interval) {\n\t\t\tsetTimeout(() => {\n\t\t\t\tsyncFiles(dirPath, fileStates, interval);\n\t\t\t}, interval);\n\t\t}\n\n\t\treturn;\n\t}\n\n\t// Initial copy of all files\n\tawait syncFiles(\n\t\targs.path,\n\t\t{ fsFileStates: {}, lixFileStates: {} },\n\t\targs.syncInterval\n\t);\n\n\treturn;\n}\n\nasync function upsertFileInLix(\n\targs: { fs: typeof fs; path: string; lix: Lix },\n\tpath: string,\n\tdata: ArrayBuffer\n) {\n\t// file is in known state with lix - means we have only changes on the fs - easy\n\t// NOTE we use file_internal for now see: https://linear.app/opral/issue/LIXDK-102/re-visit-simplifying-the-change-queue-implementation#comment-65eb3485\n\t// This means we don't see changes for the file we update via this method!\n\tawait args.lix.db\n\t\t.insertInto(\"file\") // change queue\n\t\t.values({\n\t\t\tpath: path,\n\t\t\tdata: new Uint8Array(data),\n\t\t})\n\t\t.onConflict((oc) =>\n\t\t\toc.column(\"path\").doUpdateSet({ data: new Uint8Array(data) })\n\t\t)\n\t\t.execute();\n}\n\n// TODO i guess we should move this validation logic into sdk2/src/project/loadProject.ts\nfunction categorizePlugins(plugins: readonly InlangPlugin[]): {\n\tloadMessagesPlugins: (InlangPlugin &\n\t\tRequired<Pick<InlangPlugin, \"loadMessages\">>)[];\n\tsaveMessagesPlugins: (InlangPlugin &\n\t\tRequired<Pick<InlangPlugin, \"saveMessages\">>)[];\n\timportPlugins: (InlangPlugin &\n\t\tRequired<Pick<InlangPlugin, \"importFiles\" | \"toBeImportedFiles\">>)[];\n\texportPlugins: (InlangPlugin & Required<Pick<InlangPlugin, \"exportFiles\">>)[];\n} {\n\tconst loadMessagesPlugins = plugins.filter(\n\t\t(\n\t\t\tplugin\n\t\t): plugin is InlangPlugin & Required<Pick<InlangPlugin, \"loadMessages\">> =>\n\t\t\tplugin.loadMessages !== undefined\n\t);\n\n\tconst saveMessagesPlugins = plugins.filter(\n\t\t(\n\t\t\tplugin\n\t\t): plugin is InlangPlugin & Required<Pick<InlangPlugin, \"saveMessages\">> =>\n\t\t\tplugin.saveMessages !== undefined\n\t);\n\n\tconst importPlugins = plugins.filter(\n\t\t(\n\t\t\tplugin\n\t\t): plugin is InlangPlugin &\n\t\t\tRequired<Pick<InlangPlugin, \"importFiles\" | \"toBeImportedFiles\">> =>\n\t\t\tplugin.importFiles !== undefined && plugin.toBeImportedFiles !== undefined\n\t);\n\n\tconst exportPlugins = plugins.filter(\n\t\t(\n\t\t\tplugin\n\t\t): plugin is InlangPlugin & Required<Pick<InlangPlugin, \"exportFiles\">> =>\n\t\t\tplugin.exportFiles !== undefined\n\t);\n\n\treturn {\n\t\tloadMessagesPlugins,\n\t\tsaveMessagesPlugins,\n\t\timportPlugins,\n\t\texportPlugins,\n\t};\n}\n\n/**\n * Imports local plugins for backwards compatibility.\n *\n * https://github.com/opral/inlang-sdk/issues/171\n */\nasync function importLocalPlugins(args: {\n\tfs: typeof fs;\n\tsettings: ProjectSettings;\n\tpath: string;\n\tpreprocessPluginBeforeImport?: PreprocessPluginBeforeImportFunction;\n}) {\n\tconst errors: Error[] = [];\n\tconst locallyImportedPlugins = [];\n\tfor (const module of args.settings.modules ?? []) {\n\t\tif (module.startsWith(\"http\")) {\n\t\t\tcontinue;\n\t\t}\n\t\tconst modulePath = absolutePathFromProject(args.path, module);\n\t\ttry {\n\t\t\tlet moduleAsText = await args.fs.promises.readFile(modulePath, \"utf8\");\n\t\t\tif (moduleAsText.includes(\"messageLintRule\")) {\n\t\t\t\terrors.push(new WarningDeprecatedLintRule(module));\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (args.preprocessPluginBeforeImport) {\n\t\t\t\tmoduleAsText = await args.preprocessPluginBeforeImport(moduleAsText);\n\t\t\t}\n\t\t\tconst moduleWithMimeType =\n\t\t\t\t\"data:application/javascript,\" + encodeURIComponent(moduleAsText);\n\t\t\tconst { default: plugin } = await import(\n\t\t\t\t/* @vite-ignore */ moduleWithMimeType\n\t\t\t);\n\t\t\tlocallyImportedPlugins.push(plugin);\n\t\t} catch (e) {\n\t\t\terrors.push(new PluginImportError({ plugin: module, cause: e as Error }));\n\t\t\tcontinue;\n\t\t}\n\t}\n\treturn {\n\t\terrors,\n\t\tlocallyImportedPlugins,\n\t};\n}\n\nexport class WarningDeprecatedLintRule extends Error {\n\tconstructor(module: string) {\n\t\tsuper(\n\t\t\t`The lint rule ${module} is deprecated. Please remove the lint rule from the settings. Lint rules are interim built into apps and will be succeeded by more generilizable lix validation rules.`\n\t\t);\n\t\tthis.name = \"WarningDeprecatedLintRule\";\n\t}\n}\n\n/**\n * Resolving absolute paths for fs functions.\n *\n * This mapping is required for backwards compatibility.\n * Relative paths in the project.inlang/settings.json\n * file are resolved to absolute paths with `*.inlang`\n * being pruned.\n *\n * @example\n * \"/website/project.inlang\"\n * \"./local-plugins/mock-plugin.js\"\n * -> \"/website/local-plugins/mock-plugin.js\"\n *\n */\nexport function withAbsolutePaths(\n\tfs: NodeFsPromisesSubsetLegacy,\n\tprojectPath: string\n): NodeFsPromisesSubsetLegacy {\n\treturn {\n\t\t// @ts-expect-error - node type mismatch\n\t\treadFile: (path, options) => {\n\t\t\treturn fs.readFile(absolutePathFromProject(projectPath, path), options);\n\t\t},\n\t\twriteFile: (path, data) => {\n\t\t\treturn fs.writeFile(absolutePathFromProject(projectPath, path), data);\n\t\t},\n\t\tmkdir: (path) => {\n\t\t\treturn fs.mkdir(absolutePathFromProject(projectPath, path));\n\t\t},\n\t\treaddir: (path) => {\n\t\t\treturn fs.readdir(absolutePathFromProject(projectPath, path));\n\t\t},\n\t};\n}\n\n/**\n * Joins a path from a project path.\n *\n * @example\n * joinPathFromProject(\"/project.inlang\", \"./local-plugins/mock-plugin.js\") -> \"/local-plugins/mock-plugin.js\"\n *\n * joinPathFromProject(\"/website/project.inlang\", \"./mock-plugin.js\") -> \"/website/mock-plugin.js\"\n */\nexport function absolutePathFromProject(projectPath: string, path: string) {\n\t// need to remove the project path from the module path for legacy reasons\n\t// \"/project.inlang/local-plugins/mock-plugin.js\" -> \"/local-plugins/mock-plugin.js\"\n\tconst pathWithoutProject = projectPath\n\t\t.split(nodePath.sep)\n\t\t.slice(0, -1)\n\t\t.join(nodePath.sep);\n\n\tconst resolvedPath = nodePath.resolve(pathWithoutProject, path);\n\n\treturn resolvedPath;\n}\n\nexport class ResourceFileImportError extends Error {\n\tpath: string;\n\n\tconstructor(args: { cause: Error; path: string }) {\n\t\tsuper(\"Could not import a resource file\");\n\t\tthis.name = \"ResourceFileImportError\";\n\t\tthis.cause = args.cause;\n\t\tthis.path = args.path;\n\t}\n}\n"],"names":[],"mappings":"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","debug_id":"a707cbbf-d9cd-5dca-9279-55823fc96f37"}
|
|
1
|
+
{"version":3,"file":"loadProjectFromDirectory.js","sources":["project/loadProjectFromDirectory.ts"],"sourceRoot":"/","sourcesContent":["import { newProject } from \"./newProject.js\";\nimport { loadProjectInMemory } from \"./loadProjectInMemory.js\";\nimport { type Lix } from \"@lix-js/sdk\";\nimport fs from \"node:fs\";\nimport nodePath from \"node:path\";\nimport type {\n\tInlangPlugin,\n\tNodeFsPromisesSubsetLegacy,\n} from \"../plugin/schema.js\";\nimport { fromMessageV1 } from \"../json-schema/old-v1-message/fromMessageV1.js\";\nimport type { ProjectSettings } from \"../json-schema/settings.js\";\nimport type { PreprocessPluginBeforeImportFunction } from \"../plugin/importPlugins.js\";\nimport { PluginImportError } from \"../plugin/errors.js\";\nimport { upsertBundleNestedMatchByProperties } from \"../import-export/upsertBundleNestedMatchByProperties.js\";\nimport type { ImportFile } from \"./api.js\";\n\n/**\n * Loads a project from a directory.\n *\n * Main use case are dev tools that want to load a project from a directory\n * that is stored in git.\n */\nexport async function loadProjectFromDirectory(\n\targs: { path: string; fs: typeof fs; syncInterval?: number } & Omit<\n\t\tParameters<typeof loadProjectInMemory>[0],\n\t\t\"blob\"\n\t>\n) {\n\tconst settingsPath = nodePath.join(args.path, \"settings.json\");\n\tconst settings = JSON.parse(\n\t\tawait args.fs.promises.readFile(settingsPath, \"utf8\")\n\t) as ProjectSettings;\n\n\tconst localImport = await importLocalPlugins({\n\t\tfs: args.fs,\n\t\tsettings,\n\t\tpath: args.path,\n\t});\n\n\tconst providePluginsWithLocalPlugins = [\n\t\t...(args.providePlugins ?? []),\n\t\t...localImport.locallyImportedPlugins,\n\t];\n\n\t// TODO call tempProject.lix.settled() to wait for the new settings file, and remove reload of the proejct as soon as reactive settings has landed\n\t// NOTE: we need to ensure two things:\n\t// 1. settled needs to include the changes from the copyFiles call\n\t// 2. the changes created from the copyFiles call need to be realized and lead to a signal on the settings\n\tconst project = await loadProjectInMemory({\n\t\t...args,\n\t\tprovidePlugins: providePluginsWithLocalPlugins,\n\t\tblob: await newProject({\n\t\t\tsettings,\n\t\t}),\n\t});\n\n\tawait syncLixFsFiles({\n\t\tfs: args.fs,\n\t\tpath: args.path,\n\t\tlix: project.lix,\n\t\tsyncInterval: args.syncInterval,\n\t});\n\n\tconst allPlugins = await project.plugins.get();\n\tconst { loadSavePlugins, importExportPlugins } =\n\t\tcategorizePlugins(allPlugins);\n\n\t// TODO i guess we should move this validation logic into sdk2/src/project/loadProject.ts\n\t// Two scenarios could arise:\n\t// 1. set settings is called from an app - it should detect and reject the setting of settings -> app need to be able to validate before calling set\n\t// 2. the settings file loaded from disc here is corrupted -> user has to fix the file on disc\n\tif (loadSavePlugins.length > 1) {\n\t\tthrow new Error(\n\t\t\t\"Max one loadMessages (found: \" +\n\t\t\t\tloadSavePlugins.length +\n\t\t\t\t\") and one saveMessages plugins (found: \" +\n\t\t\t\tloadSavePlugins.length +\n\t\t\t\t\") are allowed \"\n\t\t);\n\t}\n\tconst importedResourceFileErrors: Error[] = [];\n\n\t// import files from local fs\n\tfor (const plugin of importExportPlugins) {\n\t\tconst files: ImportFile[] = [];\n\t\tif (plugin.toBeImportedFiles) {\n\t\t\tconst toBeImportedFiles = await plugin.toBeImportedFiles({\n\t\t\t\tsettings: await project.settings.get(),\n\t\t\t});\n\t\t\tfor (const toBeImported of toBeImportedFiles) {\n\t\t\t\tconst absolute = absolutePathFromProject(args.path, toBeImported.path);\n\t\t\t\ttry {\n\t\t\t\t\tconst data = await args.fs.promises.readFile(absolute);\n\t\t\t\t\tfiles.push({\n\t\t\t\t\t\tlocale: toBeImported.locale,\n\t\t\t\t\t\tcontent: data,\n\t\t\t\t\t\ttoBeImportedFilesMetadata: toBeImported.metadata,\n\t\t\t\t\t});\n\t\t\t\t} catch (e) {\n\t\t\t\t\t// https://github.com/opral/inlang-sdk/issues/202\n\t\t\t\t\tif ((e as any)?.code === \"ENOENT\") {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\timportedResourceFileErrors.push(\n\t\t\t\t\t\tnew ResourceFileImportError({\n\t\t\t\t\t\t\tcause: e as Error,\n\t\t\t\t\t\t\tpath: toBeImported.path,\n\t\t\t\t\t\t})\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tawait project.importFiles({\n\t\t\tpluginKey: plugin.key,\n\t\t\tfiles,\n\t\t});\n\t}\n\n\tfor (const plugin of loadSavePlugins) {\n\t\tawait loadLegacyMessages({\n\t\t\tproject,\n\t\t\tpluginKey: plugin.key ?? plugin.id,\n\t\t\tloadMessagesFn: plugin.loadMessages!,\n\t\t\tprojectPath: args.path,\n\t\t\tfs: args.fs,\n\t\t});\n\t}\n\n\treturn {\n\t\t...project,\n\t\terrors: {\n\t\t\tget: async () => {\n\t\t\t\treturn [...localImport.errors, ...importedResourceFileErrors];\n\t\t\t},\n\t\t\t// subscribe: (\n\t\t\t// \tcallback: Parameters<InlangProject[\"errors\"][\"subscribe\"]>[0]\n\t\t\t// ) => {\n\t\t\t// \treturn project.errors.subscribe((value) => {\n\t\t\t// \t\tcallback([\n\t\t\t// \t\t\t...withLocallyImportedPluginWarning(value),\n\t\t\t// \t\t\t...localImport.errors,\n\t\t\t// \t\t\t...importedResourceFileErrors,\n\t\t\t// \t\t]);\n\t\t\t// \t});\n\t\t\t// },\n\t\t},\n\t};\n}\n\nasync function loadLegacyMessages(args: {\n\tproject: Awaited<ReturnType<typeof loadProjectInMemory>>;\n\tpluginKey: NonNullable<InlangPlugin[\"key\"] | InlangPlugin[\"id\"]>;\n\tloadMessagesFn: Required<InlangPlugin>[\"loadMessages\"];\n\tprojectPath: string;\n\tfs: typeof fs;\n}) {\n\tconst loadedLegacyMessages = await args.loadMessagesFn({\n\t\tsettings: await args.project.settings.get(),\n\t\t// @ts-expect-error - type mismatch\n\t\tnodeishFs: withAbsolutePaths(args.fs.promises, args.projectPath),\n\t});\n\tconst upsertQueries = [];\n\n\tfor (const legacyMessage of loadedLegacyMessages) {\n\t\tconst messageBundle = fromMessageV1(legacyMessage);\n\n\t\tupsertQueries.push(\n\t\t\tupsertBundleNestedMatchByProperties(args.project.db, messageBundle)\n\t\t);\n\t}\n\n\treturn await Promise.all(upsertQueries);\n}\n\ntype FsFileState = Record<\n\tstring,\n\t{\n\t\t/*mtime: number, hash: string, */ content: ArrayBuffer;\n\t\tstate: \"known\" | \"unknown\" | \"updated\" | \"gone\";\n\t}\n>;\n\nfunction arrayBuffersEqual(a: ArrayBuffer, b: ArrayBuffer) {\n\tif (a.byteLength !== b.byteLength) return false;\n\n\t// Create views for byte-by-byte comparison\n\tconst view1 = new Uint8Array(a);\n\tconst view2 = new Uint8Array(b);\n\n\t// Compare each byte\n\tfor (const [i, element] of view1.entries()) {\n\t\tif (element !== view2[i]) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\treturn true;\n}\n\n/**\n * Watches a directory and copies files into lix, keeping them in sync.\n */\nasync function syncLixFsFiles(args: {\n\tfs: typeof fs;\n\tpath: string;\n\tlix: Lix;\n\tsyncInterval?: number;\n}) {\n\t// NOTE this function is async - while it runs 100% sync in the naiv implementation - we may want to change to an async version to optimize\n\tasync function checkFsStateRecursive(\n\t\tdirPath: string,\n\t\tcurrentState: FsFileState\n\t) {\n\t\tconst entries = args.fs.readdirSync(dirPath, { withFileTypes: true });\n\n\t\tfor (const entry of entries) {\n\t\t\tconst fullPath = nodePath.join(dirPath, entry.name);\n\t\t\tif (entry.isDirectory()) {\n\t\t\t\tcheckFsStateRecursive(fullPath, currentState);\n\t\t\t} else {\n\t\t\t\t// NOTE we could start with comparing the mdate and skip file read completely...\n\t\t\t\tconst data = args.fs.readFileSync(fullPath) as unknown as ArrayBuffer;\n\n\t\t\t\tconst relativePath = \"/\" + nodePath.relative(args.path, fullPath);\n\n\t\t\t\tif (!currentState[relativePath]) {\n\t\t\t\t\tcurrentState[relativePath] = {\n\t\t\t\t\t\tcontent: data,\n\t\t\t\t\t\tstate: \"unknown\",\n\t\t\t\t\t};\n\t\t\t\t} else {\n\t\t\t\t\tif (arrayBuffersEqual(currentState[relativePath].content, data)) {\n\t\t\t\t\t\tcurrentState[relativePath].state = \"known\";\n\t\t\t\t\t} else {\n\t\t\t\t\t\tcurrentState[relativePath].state = \"updated\";\n\t\t\t\t\t\tcurrentState[relativePath].content = data;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tasync function checkLixState(currentLixState: FsFileState) {\n\t\t// go through all files in lix and check there state\n\t\tconst filesInLix = await args.lix.db\n\t\t\t.selectFrom(\"file\")\n\t\t\t.where(\"path\", \"not like\", \"%db.sqlite\")\n\t\t\t.selectAll()\n\t\t\t.execute();\n\n\t\tfor (const fileInLix of filesInLix) {\n\t\t\tconst currentStateOfFileInLix = currentLixState[fileInLix.path];\n\t\t\t// NOTE we could start with comparing the mdate and skip file read completely...\n\t\t\tif (!currentStateOfFileInLix) {\n\t\t\t\tcurrentLixState[fileInLix.path] = {\n\t\t\t\t\tcontent: new Uint8Array(fileInLix.data).buffer,\n\t\t\t\t\tstate: \"unknown\",\n\t\t\t\t};\n\t\t\t} else {\n\t\t\t\tif (\n\t\t\t\t\tarrayBuffersEqual(\n\t\t\t\t\t\tcurrentStateOfFileInLix.content,\n\t\t\t\t\t\tfileInLix.data.buffer as ArrayBuffer\n\t\t\t\t\t)\n\t\t\t\t) {\n\t\t\t\t\tcurrentStateOfFileInLix.state = \"known\";\n\t\t\t\t} else {\n\t\t\t\t\tcurrentStateOfFileInLix.state = \"updated\";\n\t\t\t\t\tcurrentStateOfFileInLix.content = fileInLix.data\n\t\t\t\t\t\t.buffer as ArrayBuffer;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tasync function syncUpFsAndLixFiles(statesToSync: {\n\t\tfsFileStates: FsFileState;\n\t\tlixFileStates: FsFileState;\n\t}) {\n\t\t// for (const file of Object.keys(statesToSync.fsFileStates)) {\n\t\t// \tif (file.includes(\"gitignore\"))\n\t\t// \t\tconsole.log(\n\t\t// \t\t\t\"fsFileStates : \" +\n\t\t// \t\t\t\tfile +\n\t\t// \t\t\t\t\" fs \" +\n\t\t// \t\t\t\tstatesToSync.fsFileStates[file]?.state +\n\t\t// \t\t\t\t\" lix \" +\n\t\t// \t\t\t\tstatesToSync.lixFileStates[file]?.state\n\t\t// \t\t);\n\t\t// }\n\n\t\t// Sync cases:\n\t\t// fs - no state for file | fs - unkonwn | fs - known | fs - updated | fs - gone\n\t\t// lix - no state for file \tNOTHING\t(1)\t | ADD TO LIX(2) | ERROR (3) | ERROR (4) | ERROR (5)\n\t\t// lix - unknown\t\t\t\t\tADD TO FS (6) | USE FS VER.(7) | ERROR (8) | CASE (9) | CASE (10)\n\t\t// lix - known ERROR (11) | ERROR (12) | NOTHING(13) | ERROR (14) | ERROR (15)\n\t\t// lix - updated\t\t\t\t\tERROR (16) | ERROR (17) | USE LIX (18) | CASE (19) | CASE (20)\n\t\t// lix - gone \t\t\t\t\t\tERROR (21) | ERROR (22) | DELETE FS (23)| CASE (24) | CASE (25)\n\n\t\t// TODO check export import from saveFileToDirectory\n\n\t\tfor (const [path, fsState] of Object.entries(statesToSync.fsFileStates)) {\n\t\t\t// no state for file in LIX\n\t\t\tif (!statesToSync.lixFileStates[path]) {\n\t\t\t\tif (fsState.state === \"unknown\") {\n\t\t\t\t\t// ADD TO LIX(2)\n\t\t\t\t\tawait upsertFileInLix(args, path, fsState.content);\n\t\t\t\t\tstatesToSync.lixFileStates[path] = {\n\t\t\t\t\t\tstate: \"known\",\n\t\t\t\t\t\tcontent: fsState.content,\n\t\t\t\t\t};\n\t\t\t\t\tfsState.state = \"known\";\n\t\t\t\t} else {\n\t\t\t\t\t// ERROR (3), ERROR (4), ERROR (5)\n\t\t\t\t\t// The file does not exist in lix but its state differs from unknown?\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\"Illeagal lix<->fs sync state. The file [\" +\n\t\t\t\t\t\t\tpath +\n\t\t\t\t\t\t\t\"] that was \" +\n\t\t\t\t\t\t\tfsState.state +\n\t\t\t\t\t\t\t\" on disc did not exit in lix\"\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tconst lixState = statesToSync.lixFileStates[path];\n\t\t\t\tif (fsState.state === \"unknown\") {\n\t\t\t\t\tif (lixState.state === \"unknown\") {\n\t\t\t\t\t\tif (arrayBuffersEqual(lixState.content, fsState.content)) {\n\t\t\t\t\t\t\tlixState.state = \"known\";\n\t\t\t\t\t\t\tfsState.state = \"known\";\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tawait upsertFileInLix(args, path, fsState.content);\n\t\t\t\t\t\t\tlixState.content = fsState.content;\n\t\t\t\t\t\t\tlixState.state = \"known\";\n\t\t\t\t\t\t\tfsState.state = \"known\";\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// ERROR 12, 17, 22\n\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t\"Illeagal lix<->fs sync state. The file [\" +\n\t\t\t\t\t\t\t\tpath +\n\t\t\t\t\t\t\t\t\"] that was \" +\n\t\t\t\t\t\t\t\tfsState.state +\n\t\t\t\t\t\t\t\t\" but did exist in lix already\"\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t} else if (fsState.state === \"known\") {\n\t\t\t\t\tif (lixState.state === \"known\") {\n\t\t\t\t\t\t// NO OP - NOTHING(13)\n\t\t\t\t\t} else if (lixState.state === \"updated\") {\n\t\t\t\t\t\t// USE LIX (18)\n\t\t\t\t\t\targs.fs.writeFileSync(\n\t\t\t\t\t\t\t// TODO check platform dependent folder separator\n\t\t\t\t\t\t\targs.path + path,\n\t\t\t\t\t\t\tBuffer.from(lixState.content)\n\t\t\t\t\t\t);\n\t\t\t\t\t\tfsState.content = lixState.content;\n\t\t\t\t\t\tfsState.state = \"known\";\n\t\t\t\t\t\tlixState.state = \"known\";\n\t\t\t\t\t} else if (lixState.state === \"gone\") {\n\t\t\t\t\t\t// DELETE FS (23)\n\t\t\t\t\t\targs.fs.unlinkSync(args.path + path);\n\t\t\t\t\t\tfsState.state = \"gone\";\n\t\t\t\t\t\tlixState.state = \"gone\";\n\t\t\t\t\t}\n\t\t\t\t} else if (fsState.state === \"updated\") {\n\t\t\t\t\tif (lixState.state === \"unknown\") {\n\t\t\t\t\t\t// TODO A file was added to lix while a known file from fs was updated?\n\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t\"Illeagal lix<->fs sync state. The file [\" +\n\t\t\t\t\t\t\t\tpath +\n\t\t\t\t\t\t\t\t\"] that was \" +\n\t\t\t\t\t\t\t\tfsState.state +\n\t\t\t\t\t\t\t\t\" but it was not known by lix yet?\"\n\t\t\t\t\t\t);\n\t\t\t\t\t} else if (lixState.state === \"known\") {\n\t\t\t\t\t\tawait upsertFileInLix(args, path, fsState.content);\n\t\t\t\t\t\tlixState.content = fsState.content;\n\n\t\t\t\t\t\tfsState.state = \"known\";\n\t\t\t\t\t} else if (lixState.state === \"updated\") {\n\t\t\t\t\t\t// seems like we saw an update on the file in fs while some changes on lix have not been reached fs? FS -> Winns?\n\t\t\t\t\t\tconsole.warn(\n\t\t\t\t\t\t\t\"seems like we saw an update on the file \" +\n\t\t\t\t\t\t\t\tpath +\n\t\t\t\t\t\t\t\t\" in fs while some changes on lix have not been reached fs? FS -> Winns?\"\n\t\t\t\t\t\t);\n\t\t\t\t\t\tawait upsertFileInLix(args, path, fsState.content);\n\t\t\t\t\t\tlixState.content = fsState.content;\n\t\t\t\t\t\tlixState.state = \"known\";\n\t\t\t\t\t\tfsState.state = \"known\";\n\t\t\t\t\t} else if (lixState.state === \"gone\") {\n\t\t\t\t\t\tconsole.warn(\n\t\t\t\t\t\t\t\"seems like we saw an delete in lix while some changes on fs have not been reached fs? FS -> Winns?\"\n\t\t\t\t\t\t);\n\t\t\t\t\t\t// TODO update the lix state\n\t\t\t\t\t\tlixState.content = fsState.content;\n\t\t\t\t\t\tlixState.state = \"known\";\n\t\t\t\t\t\tfsState.state = \"known\";\n\t\t\t\t\t}\n\t\t\t\t} else if (fsState.state === \"gone\") {\n\t\t\t\t\tif (lixState.state === \"unknown\") {\n\t\t\t\t\t\t// TODO A file was added to lix while a known file from fs was removed?\n\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t\"Illeagal lix<->fs sync state. The file [\" +\n\t\t\t\t\t\t\t\tpath +\n\t\t\t\t\t\t\t\t\"] that was \" +\n\t\t\t\t\t\t\t\tfsState.state +\n\t\t\t\t\t\t\t\t\" but it was not known by lix yet?\"\n\t\t\t\t\t\t);\n\t\t\t\t\t} else if (lixState.state === \"known\") {\n\t\t\t\t\t\t// file is in known state with lix - means we have only changes on the fs - easy\n\t\t\t\t\t\tawait args.lix.db\n\t\t\t\t\t\t\t.deleteFrom(\"file\")\n\t\t\t\t\t\t\t.where(\"path\", \"=\", path)\n\t\t\t\t\t\t\t.execute();\n\t\t\t\t\t\t// NOTE: states where both are gone will get removed in the lix state loop\n\t\t\t\t\t\tlixState.state = \"gone\";\n\t\t\t\t\t} else if (lixState.state === \"updated\") {\n\t\t\t\t\t\t// seems like we saw an update on the file in fs while some changes on lix have not been reached fs? FS -> Winns?\n\t\t\t\t\t\tconsole.warn(\n\t\t\t\t\t\t\t\"seems like we saw an update on the file in fs while some changes on lix have not been reached fs? FS -> Winns?\"\n\t\t\t\t\t\t);\n\t\t\t\t\t\tawait args.lix.db\n\t\t\t\t\t\t\t.deleteFrom(\"file\")\n\t\t\t\t\t\t\t.where(\"path\", \"=\", path)\n\t\t\t\t\t\t\t.execute();\n\t\t\t\t\t\t// NOTE: states where both are gone will get removed in the lix state loop\n\t\t\t\t\t\tlixState.state = \"gone\";\n\t\t\t\t\t\tfsState.state = \"gone\";\n\t\t\t\t\t} else if (lixState.state === \"gone\") {\n\t\t\t\t\t\tconsole.warn(\n\t\t\t\t\t\t\t\"seems like we saw an delete in lix while we have a delete in lix simultaniously?\"\n\t\t\t\t\t\t);\n\t\t\t\t\t\tlixState.state = \"gone\";\n\t\t\t\t\t\tfsState.state = \"gone\";\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tfor (const [path, lixState] of Object.entries(statesToSync.lixFileStates)) {\n\t\t\t// no state for file in fs\n\t\t\tif (!statesToSync.fsFileStates[path]) {\n\t\t\t\tif (lixState.state == \"unknown\") {\n\t\t\t\t\t// ADD TO FS (6)\n\t\t\t\t\t// create directory if not exists\n\t\t\t\t\targs.fs.mkdirSync(nodePath.dirname(nodePath.join(args.path, path)), {\n\t\t\t\t\t\trecursive: true,\n\t\t\t\t\t});\n\t\t\t\t\t// write file\n\t\t\t\t\targs.fs.writeFileSync(\n\t\t\t\t\t\tnodePath.join(args.path, path),\n\t\t\t\t\t\tBuffer.from(lixState.content)\n\t\t\t\t\t);\n\t\t\t\t\tstatesToSync.fsFileStates[path] = {\n\t\t\t\t\t\tstate: \"known\",\n\t\t\t\t\t\tcontent: lixState.content,\n\t\t\t\t\t};\n\t\t\t\t} else {\n\t\t\t\t\t// ERROR (11) 16 21\n\t\t\t\t\t// The file does not exist on fs but its state differs from unknown?\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\"Illeagal lix<->fs sync state. The file [\" +\n\t\t\t\t\t\t\tpath +\n\t\t\t\t\t\t\t\"] that was in the state\" +\n\t\t\t\t\t\t\tlixState.state +\n\t\t\t\t\t\t\t\" for lix did not exist on disk\"\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (\n\t\t\t\t\tlixState.state === \"gone\" &&\n\t\t\t\t\tstatesToSync.fsFileStates[path].state === \"gone\"\n\t\t\t\t) {\n\t\t\t\t\tdelete statesToSync.lixFileStates[path];\n\t\t\t\t\tdelete statesToSync.fsFileStates[path];\n\t\t\t\t} else if (lixState.state !== statesToSync.fsFileStates[path].state) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\"At this stage both states should be in sync lix state \" +\n\t\t\t\t\t\t\tlixState.state +\n\t\t\t\t\t\t\t\" fs state \" +\n\t\t\t\t\t\t\tstatesToSync.fsFileStates[path].state\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tasync function syncFiles(\n\t\tdirPath: string,\n\t\tfileStates: {\n\t\t\tlixFileStates: FsFileState;\n\t\t\tfsFileStates: FsFileState;\n\t\t},\n\t\tinterval?: number\n\t) {\n\t\t// mark all states as removed - checkFsStateRecursive will update those that exist on the disc correspondingly\n\t\tfor (const fsState of Object.values(fileStates.fsFileStates)) {\n\t\t\tfsState.state = \"gone\";\n\t\t}\n\n\t\t// mark all states as removed - checkFsStateRecursive will update those that exist on the disc correspondingly\n\t\tfor (const lixState of Object.values(fileStates.lixFileStates)) {\n\t\t\tlixState.state = \"gone\";\n\t\t}\n\n\t\t// read states from disc - detect changes\n\t\tawait checkFsStateRecursive(dirPath, fileStates.fsFileStates);\n\n\t\t// read states form lix - detect changes\n\t\tawait checkLixState(fileStates.lixFileStates);\n\n\t\t// sync fs<->lix\n\t\tawait syncUpFsAndLixFiles(fileStates);\n\n\t\tif (interval) {\n\t\t\tsetTimeout(() => {\n\t\t\t\tsyncFiles(dirPath, fileStates, interval);\n\t\t\t}, interval);\n\t\t}\n\n\t\treturn;\n\t}\n\n\t// Initial copy of all files\n\tawait syncFiles(\n\t\targs.path,\n\t\t{ fsFileStates: {}, lixFileStates: {} },\n\t\targs.syncInterval\n\t);\n\n\treturn;\n}\n\nasync function upsertFileInLix(\n\targs: { fs: typeof fs; path: string; lix: Lix },\n\tpath: string,\n\tdata: ArrayBuffer\n) {\n\t// file is in known state with lix - means we have only changes on the fs - easy\n\t// NOTE we use file_internal for now see: https://linear.app/opral/issue/LIXDK-102/re-visit-simplifying-the-change-queue-implementation#comment-65eb3485\n\t// This means we don't see changes for the file we update via this method!\n\tawait args.lix.db\n\t\t.insertInto(\"file\") // change queue\n\t\t.values({\n\t\t\tpath: path,\n\t\t\tdata: new Uint8Array(data),\n\t\t})\n\t\t.onConflict((oc) =>\n\t\t\toc.column(\"path\").doUpdateSet({ data: new Uint8Array(data) })\n\t\t)\n\t\t.execute();\n}\n/**\n * Filters legacy load and save messages plugins.\n *\n * Legacy plugins are plugins that implement loadMessages and saveMessages but not importFiles and exportFiles.\n */\nfunction categorizePlugins(plugins: readonly InlangPlugin[]) {\n\tconst loadSavePlugins: InlangPlugin[] = [];\n\tconst importExportPlugins: InlangPlugin[] = [];\n\n\tfor (const plugin of plugins) {\n\t\tif (\n\t\t\tplugin.loadMessages &&\n\t\t\tplugin.saveMessages &&\n\t\t\t!(plugin.importFiles && plugin.exportFiles)\n\t\t) {\n\t\t\tloadSavePlugins.push(plugin);\n\t\t} else if (plugin.importFiles || plugin.exportFiles) {\n\t\t\timportExportPlugins.push(plugin);\n\t\t}\n\t}\n\n\treturn { loadSavePlugins, importExportPlugins };\n}\n\n/**\n * Imports local plugins for backwards compatibility.\n *\n * https://github.com/opral/inlang-sdk/issues/171\n */\nasync function importLocalPlugins(args: {\n\tfs: typeof fs;\n\tsettings: ProjectSettings;\n\tpath: string;\n\tpreprocessPluginBeforeImport?: PreprocessPluginBeforeImportFunction;\n}) {\n\tconst errors: Error[] = [];\n\tconst locallyImportedPlugins = [];\n\tfor (const module of args.settings.modules ?? []) {\n\t\tif (module.startsWith(\"http\")) {\n\t\t\tcontinue;\n\t\t}\n\t\tconst modulePath = absolutePathFromProject(args.path, module);\n\t\ttry {\n\t\t\tlet moduleAsText = await args.fs.promises.readFile(modulePath, \"utf8\");\n\t\t\tif (moduleAsText.includes(\"messageLintRule\")) {\n\t\t\t\terrors.push(new WarningDeprecatedLintRule(module));\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (args.preprocessPluginBeforeImport) {\n\t\t\t\tmoduleAsText = await args.preprocessPluginBeforeImport(moduleAsText);\n\t\t\t}\n\t\t\tconst moduleWithMimeType =\n\t\t\t\t\"data:application/javascript,\" + encodeURIComponent(moduleAsText);\n\t\t\tconst { default: plugin } = await import(\n\t\t\t\t/* @vite-ignore */ moduleWithMimeType\n\t\t\t);\n\t\t\tlocallyImportedPlugins.push(plugin);\n\t\t} catch (e) {\n\t\t\terrors.push(new PluginImportError({ plugin: module, cause: e as Error }));\n\t\t\tcontinue;\n\t\t}\n\t}\n\treturn {\n\t\terrors,\n\t\tlocallyImportedPlugins,\n\t};\n}\n\nexport class WarningDeprecatedLintRule extends Error {\n\tconstructor(module: string) {\n\t\tsuper(\n\t\t\t`The lint rule ${module} is deprecated. Please remove the lint rule from the settings. Lint rules are interim built into apps and will be succeeded by more generilizable lix validation rules.`\n\t\t);\n\t\tthis.name = \"WarningDeprecatedLintRule\";\n\t}\n}\n\n/**\n * Resolving absolute paths for fs functions.\n *\n * This mapping is required for backwards compatibility.\n * Relative paths in the project.inlang/settings.json\n * file are resolved to absolute paths with `*.inlang`\n * being pruned.\n *\n * @example\n * \"/website/project.inlang\"\n * \"./local-plugins/mock-plugin.js\"\n * -> \"/website/local-plugins/mock-plugin.js\"\n *\n */\nexport function withAbsolutePaths(\n\tfs: NodeFsPromisesSubsetLegacy,\n\tprojectPath: string\n): NodeFsPromisesSubsetLegacy {\n\treturn {\n\t\t// @ts-expect-error - node type mismatch\n\t\treadFile: (path, options) => {\n\t\t\treturn fs.readFile(absolutePathFromProject(projectPath, path), options);\n\t\t},\n\t\twriteFile: (path, data) => {\n\t\t\treturn fs.writeFile(absolutePathFromProject(projectPath, path), data);\n\t\t},\n\t\tmkdir: (path) => {\n\t\t\treturn fs.mkdir(absolutePathFromProject(projectPath, path));\n\t\t},\n\t\treaddir: (path) => {\n\t\t\treturn fs.readdir(absolutePathFromProject(projectPath, path));\n\t\t},\n\t};\n}\n\n/**\n * Joins a path from a project path.\n *\n * @example\n * joinPathFromProject(\"/project.inlang\", \"./local-plugins/mock-plugin.js\") -> \"/local-plugins/mock-plugin.js\"\n *\n * joinPathFromProject(\"/website/project.inlang\", \"./mock-plugin.js\") -> \"/website/mock-plugin.js\"\n */\nexport function absolutePathFromProject(projectPath: string, path: string) {\n\t// need to remove the project path from the module path for legacy reasons\n\t// \"/project.inlang/local-plugins/mock-plugin.js\" -> \"/local-plugins/mock-plugin.js\"\n\tconst pathWithoutProject = projectPath\n\t\t.split(nodePath.sep)\n\t\t.slice(0, -1)\n\t\t.join(nodePath.sep);\n\n\tconst resolvedPath = nodePath.resolve(pathWithoutProject, path);\n\n\treturn resolvedPath;\n}\n\nexport class ResourceFileImportError extends Error {\n\tpath: string;\n\n\tconstructor(args: { cause: Error; path: string }) {\n\t\tsuper(\"Could not import a resource file\");\n\t\tthis.name = \"ResourceFileImportError\";\n\t\tthis.cause = args.cause;\n\t\tthis.path = args.path;\n\t}\n}\n"],"names":[],"mappings":"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","debug_id":"effafa39-b15a-55ff-a980-555f1b5eaed5"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
2
2
|
|
|
3
|
-
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="
|
|
3
|
+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="a2e360a7-8037-526f-b036-d39152e1fa8a")}catch(e){}}();
|
|
4
4
|
import { beforeEach, describe, expect, test, vi } from "vitest";
|
|
5
5
|
import { ProjectSettings } from "../json-schema/settings.js";
|
|
6
6
|
import { fs, vol, Volume } from "memfs";
|
|
@@ -513,7 +513,6 @@ test("it should pass toBeImportedMetadata on import", async () => {
|
|
|
513
513
|
expect(importSpy).toHaveBeenCalledWith(expect.objectContaining({
|
|
514
514
|
files: [
|
|
515
515
|
expect.objectContaining({
|
|
516
|
-
name: "en.json",
|
|
517
516
|
toBeImportedFilesMetadata: {
|
|
518
517
|
foo: "bar",
|
|
519
518
|
},
|
|
@@ -659,5 +658,62 @@ test("it can import plugins via http", async () => {
|
|
|
659
658
|
.execute();
|
|
660
659
|
expect(pluginCache.some((file) => new TextDecoder().decode(file.data) === mockPluginModule), "expecting the plugin to be cached").toBe(true);
|
|
661
660
|
});
|
|
661
|
+
test("plugins that provide both loadMessages and importFiles should be allowed and the importFiles should be called", async () => {
|
|
662
|
+
const mockRepo = {
|
|
663
|
+
"/project.inlang/settings.json": JSON.stringify({
|
|
664
|
+
baseLocale: "en",
|
|
665
|
+
locales: ["en"],
|
|
666
|
+
modules: [],
|
|
667
|
+
}),
|
|
668
|
+
};
|
|
669
|
+
const fs = Volume.fromJSON(mockRepo);
|
|
670
|
+
const mockPlugin = {
|
|
671
|
+
key: "mock-plugin",
|
|
672
|
+
loadMessages: vi.fn(async () => []),
|
|
673
|
+
importFiles: vi.fn(async () => {
|
|
674
|
+
return { bundles: [], messages: [], variants: [] };
|
|
675
|
+
}),
|
|
676
|
+
};
|
|
677
|
+
const project = await loadProjectFromDirectory({
|
|
678
|
+
fs: fs,
|
|
679
|
+
path: "/project.inlang",
|
|
680
|
+
providePlugins: [mockPlugin],
|
|
681
|
+
});
|
|
682
|
+
expect(mockPlugin.importFiles).toHaveBeenCalled();
|
|
683
|
+
expect(mockPlugin.loadMessages).not.toHaveBeenCalled();
|
|
684
|
+
});
|
|
685
|
+
test("providing multiple plugins that have legacy loadMessages and saveMessages function should be possible if they have import/export functions", async () => {
|
|
686
|
+
const mockRepo = {
|
|
687
|
+
"/project.inlang/settings.json": JSON.stringify({
|
|
688
|
+
baseLocale: "en",
|
|
689
|
+
locales: ["en"],
|
|
690
|
+
modules: [],
|
|
691
|
+
}),
|
|
692
|
+
};
|
|
693
|
+
const fs = Volume.fromJSON(mockRepo);
|
|
694
|
+
const mockPlugin1 = {
|
|
695
|
+
key: "mock-plugin1",
|
|
696
|
+
loadMessages: vi.fn(async () => []),
|
|
697
|
+
importFiles: vi.fn(async () => {
|
|
698
|
+
return { bundles: [], messages: [], variants: [] };
|
|
699
|
+
}),
|
|
700
|
+
};
|
|
701
|
+
const mockPlugin2 = {
|
|
702
|
+
key: "mock-plugin2",
|
|
703
|
+
loadMessages: vi.fn(async () => []),
|
|
704
|
+
importFiles: vi.fn(async () => {
|
|
705
|
+
return { bundles: [], messages: [], variants: [] };
|
|
706
|
+
}),
|
|
707
|
+
};
|
|
708
|
+
const project = await loadProjectFromDirectory({
|
|
709
|
+
fs: fs,
|
|
710
|
+
path: "/project.inlang",
|
|
711
|
+
providePlugins: [mockPlugin1, mockPlugin2],
|
|
712
|
+
});
|
|
713
|
+
expect(mockPlugin1.importFiles).toHaveBeenCalled();
|
|
714
|
+
expect(mockPlugin1.loadMessages).not.toHaveBeenCalled();
|
|
715
|
+
expect(mockPlugin2.importFiles).toHaveBeenCalled();
|
|
716
|
+
expect(mockPlugin2.loadMessages).not.toHaveBeenCalled();
|
|
717
|
+
});
|
|
662
718
|
//# sourceMappingURL=loadProjectFromDirectory.test.js.map
|
|
663
|
-
//# debugId=
|
|
719
|
+
//# debugId=a2e360a7-8037-526f-b036-d39152e1fa8a
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loadProjectFromDirectory.test.js","sources":["project/loadProjectFromDirectory.test.ts"],"sourceRoot":"/","sourcesContent":["/* eslint-disable @typescript-eslint/no-unused-vars */\n\nimport { beforeEach, describe, expect, test, vi } from \"vitest\";\nimport { ProjectSettings } from \"../json-schema/settings.js\";\nimport { fs, vol, Volume } from \"memfs\";\nimport {\n\tloadProjectFromDirectory,\n\tResourceFileImportError,\n\tWarningDeprecatedLintRule,\n} from \"./loadProjectFromDirectory.js\";\nimport { selectBundleNested } from \"../query-utilities/selectBundleNested.js\";\nimport { Text } from \"../json-schema/pattern.js\";\nimport type { InlangPlugin } from \"../plugin/schema.js\";\nimport type {\n\tMessageV1,\n\tVariantV1,\n} from \"../json-schema/old-v1-message/schemaV1.js\";\nimport { saveProjectToDirectory } from \"./saveProjectToDirectory.js\";\nimport { insertBundleNested } from \"../query-utilities/insertBundleNested.js\";\n\ntest(\"plugin.loadMessages and plugin.saveMessages must not be configured together with import export\", async () => {\n\tconst mockLegacyPlugin: InlangPlugin = {\n\t\tkey: \"mock-legacy-plugin\",\n\t\tloadMessages: async () => {\n\t\t\treturn [];\n\t\t},\n\t\tsaveMessages: async () => {},\n\t};\n\n\tconst mockLegacyPlugin2: InlangPlugin = {\n\t\tkey: \"mock-legacy-plugin-2\",\n\t\tloadMessages: async () => {\n\t\t\treturn [];\n\t\t},\n\t\tsaveMessages: async () => {},\n\t};\n\n\tconst mockImportExportPlugin: InlangPlugin = {\n\t\tkey: \"mock-import-export-plugin\",\n\t\texportFiles: () => {\n\t\t\treturn [];\n\t\t},\n\t\timportFiles: () => {\n\t\t\treturn {} as any;\n\t\t},\n\t};\n\n\tawait expect(\n\t\t(async () => {\n\t\t\tawait loadProjectFromDirectory({\n\t\t\t\tfs: Volume.fromJSON({\n\t\t\t\t\t\"./project.inlang/settings.json\": JSON.stringify({\n\t\t\t\t\t\tbaseLocale: \"en\",\n\t\t\t\t\t\tlocales: [\"en\", \"de\"],\n\t\t\t\t\t\tmodules: [],\n\t\t\t\t\t} satisfies ProjectSettings),\n\t\t\t\t}) as any,\n\t\t\t\tpath: \"./project.inlang\",\n\t\t\t\tprovidePlugins: [\n\t\t\t\t\tmockLegacyPlugin,\n\t\t\t\t\tmockLegacyPlugin2,\n\t\t\t\t\tmockImportExportPlugin,\n\t\t\t\t],\n\t\t\t});\n\t\t})()\n\t).rejects.toThrowError();\n\n\tawait expect(\n\t\t(async () => {\n\t\t\tawait loadProjectFromDirectory({\n\t\t\t\tfs: Volume.fromJSON({\n\t\t\t\t\t\"./project.inlang/settings.json\": JSON.stringify({\n\t\t\t\t\t\tbaseLocale: \"en\",\n\t\t\t\t\t\tlocales: [\"en\", \"de\"],\n\t\t\t\t\t\tmodules: [],\n\t\t\t\t\t} satisfies ProjectSettings),\n\t\t\t\t}) as any,\n\t\t\t\tpath: \"./project.inlang\",\n\t\t\t\tprovidePlugins: [\n\t\t\t\t\tmockLegacyPlugin,\n\t\t\t\t\tmockLegacyPlugin2,\n\t\t\t\t\tmockImportExportPlugin,\n\t\t\t\t],\n\t\t\t});\n\t\t})()\n\t).rejects.toThrowError();\n});\n\ntest(\"plugin.loadMessages and plugin.saveMessages should work for legacy purposes\", async () => {\n\tconst mockLegacyPlugin: InlangPlugin = {\n\t\tid: \"mock-legacy-plugin\",\n\t\t// @ts-expect-error - id is deprecated, key can be undefined\n\t\tkey: undefined,\n\t\tloadMessages: async ({ nodeishFs, settings }) => {\n\t\t\tconst pathPattern = settings[\"plugin.mock-plugin\"]?.pathPattern as string;\n\n\t\t\tconst messages: MessageV1[] = [];\n\n\t\t\t// @ts-expect-error - language tag is always given by the sdk v2\n\t\t\tfor (const languageTag of settings.languageTags) {\n\t\t\t\tconst data = await nodeishFs.readFile(\n\t\t\t\t\tpathPattern.replace(\"{languageTag}\", languageTag)\n\t\t\t\t);\n\n\t\t\t\tfor (const [key, value] of Object.entries(\n\t\t\t\t\tJSON.parse(data.toString())\n\t\t\t\t)) {\n\t\t\t\t\tconst exisitngMessage = messages.find(\n\t\t\t\t\t\t(message) => message.id === key\n\t\t\t\t\t);\n\t\t\t\t\tconst variant = {\n\t\t\t\t\t\tlanguageTag: languageTag,\n\t\t\t\t\t\tmatch: [],\n\t\t\t\t\t\tpattern: [{ type: \"Text\", value: value }],\n\t\t\t\t\t} as VariantV1;\n\t\t\t\t\tif (exisitngMessage !== undefined) {\n\t\t\t\t\t\texisitngMessage.variants.push(variant);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tmessages.push({\n\t\t\t\t\t\t\talias: {},\n\t\t\t\t\t\t\tid: key,\n\t\t\t\t\t\t\tselectors: [],\n\t\t\t\t\t\t\tvariants: [variant],\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn messages;\n\t\t},\n\t\tsaveMessages: async ({ messages, nodeishFs, settings }) => {\n\t\t\tconst pathPattern = settings[\"plugin.mock-plugin\"]?.pathPattern as string;\n\t\t\tfor (const languageTag of settings.languageTags!) {\n\t\t\t\tconst messagesInLanguage = {} as Record<string, string>;\n\t\t\t\tfor (const message of messages) {\n\t\t\t\t\tconst variantsInLanguage = message.variants.filter(\n\t\t\t\t\t\t(variant) => variant.languageTag === languageTag\n\t\t\t\t\t);\n\t\t\t\t\tif (variantsInLanguage.length > 1) {\n\t\t\t\t\t\t// data will get lost during export => throw?\n\t\t\t\t\t} else if (variantsInLanguage.length === 1) {\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\tvariantsInLanguage[0]!.pattern.length != 1 ||\n\t\t\t\t\t\t\tvariantsInLanguage[0]!.pattern[0]?.type !== \"Text\"\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t// throw?\n\t\t\t\t\t\t}\n\t\t\t\t\t\tmessagesInLanguage[message.id] = (\n\t\t\t\t\t\t\tvariantsInLanguage[0]!.pattern[0]! as any\n\t\t\t\t\t\t).value;\n\t\t\t\t\t}\n\t\t\t\t\t// else no-op\n\t\t\t\t}\n\t\t\t\tawait nodeishFs.writeFile(\n\t\t\t\t\tpathPattern.replace(\"{languageTag}\", languageTag),\n\t\t\t\t\tJSON.stringify(messagesInLanguage, null, 2)\n\t\t\t\t);\n\t\t\t}\n\t\t},\n\t};\n\tconst mockRepo = {\n\t\t\"./README.md\": \"# Hello World\",\n\t\t\"./src/index.js\": \"console.log('Hello World')\",\n\t\t\"./src/translations/en.json\": JSON.stringify({\n\t\t\tkey1: \"value1\",\n\t\t\tkey2: \"value2\",\n\t\t}),\n\t\t\"./src/translations/de.json\": JSON.stringify({\n\t\t\tkey1: \"wert1\",\n\t\t\tkey2: \"wert2\",\n\t\t}),\n\t\t\"./project.inlang/settings.json\": JSON.stringify({\n\t\t\tbaseLocale: \"en\",\n\t\t\tlocales: [\"en\", \"de\"],\n\t\t\tmodules: [\"./mock-module.js\"],\n\t\t\t\"plugin.mock-plugin\": {\n\t\t\t\tpathPattern: \"./src/translations/{languageTag}.json\",\n\t\t\t},\n\t\t} satisfies ProjectSettings),\n\t};\n\n\tconst fs = Volume.fromJSON(mockRepo);\n\n\tlet project = await loadProjectFromDirectory({\n\t\tfs: fs as any,\n\t\tpath: \"./project.inlang\",\n\t\tprovidePlugins: [mockLegacyPlugin],\n\t});\n\n\tawait insertBundleNested(project.db, {\n\t\tid: \"key-id\",\n\t\tmessages: [\n\t\t\t{\n\t\t\t\tid: \"mock-message\",\n\t\t\t\tbundleId: \"mock-bundle\",\n\t\t\t\tlocale: \"en\",\n\t\t\t\tselectors: [],\n\t\t\t\tvariants: [\n\t\t\t\t\t{\n\t\t\t\t\t\tmessageId: \"mock-message\",\n\t\t\t\t\t\tpattern: [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\ttype: \"text\",\n\t\t\t\t\t\t\t\tvalue: \"JOJO\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t],\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t},\n\t\t],\n\t});\n\n\tawait saveProjectToDirectory({\n\t\tfs: fs.promises as any,\n\t\tpath: \"./project.inlang\",\n\t\tproject,\n\t});\n\n\tproject = await loadProjectFromDirectory({\n\t\tfs: fs as any,\n\t\tpath: \"./project.inlang\",\n\t\tprovidePlugins: [mockLegacyPlugin],\n\t});\n\n\tconst bundles = await selectBundleNested(project.db).execute();\n\n\tconst bundlesOrdered = bundles.sort((a, b) => a.id.localeCompare(b.id));\n\n\texpect(bundles.length).toBe(3);\n\texpect(bundlesOrdered[0]?.messages[0]?.locale).toBe(\"en\");\n\texpect(\n\t\t(bundlesOrdered[0]?.messages[0]?.variants[0]?.pattern[0] as Text)?.value\n\t).toBe(\"JOJO\");\n\n\t// TODO fix\n\t// expect(bundlesOrdered[0]?.messages[9]?.locale).toBe(\"en\");\n\t// expect(\n\t// \t(bundlesOrdered[0]?.messages[1]?.variants[0]?.pattern[0] as Text)?.value\n\t// ).toBe(\"wert1\");\n\n\t// expect(bundlesOrdered[1]?.messages[0]?.locale).toBe(\"en\");\n\t// expect(\n\t// \t(bundlesOrdered[1]?.messages[0]?.variants[0]?.pattern[0] as Text)?.value\n\t// ).toBe(\"value2\");\n\n\t// expect(bundlesOrdered[1]?.messages[1]?.locale).toBe(\"de\");\n\t// expect(\n\t// \t(bundlesOrdered[1]?.messages[1]?.variants[0]?.pattern[0] as Text)?.value\n\t// ).toBe(\"wert2\");\n});\n\nconst mockSettings = {\n\tbaseLocale: \"en\",\n\tlocales: [\"en\", \"de\"],\n\tmodules: [],\n} satisfies ProjectSettings;\n\nconst mockDirectory = {\n\t\"/project.inlang/cache/plugin/29j49j2\": \"cache value\",\n\t\"/project.inlang/.gitignore\": \"git value\",\n\t\"/project.inlang/prettierrc.json\": \"prettier value\",\n\t\"/project.inlang/README.md\": \"readme value\",\n\t\"/project.inlang/settings.json\": JSON.stringify(mockSettings),\n};\n\ndescribe(\"it should keep files between the inlang directory and lix in sync\", async () => {\n\ttest(\"files from directory should be available via lix after project has been loaded from directory\", async () => {\n\t\tconst syncInterval = 100;\n\t\tconst fs = Volume.fromJSON(mockDirectory);\n\n\t\tconst project = await loadProjectFromDirectory({\n\t\t\tfs: fs as any,\n\t\t\tpath: \"/project.inlang\",\n\t\t\tsyncInterval: syncInterval,\n\t\t});\n\n\t\tconst files = await project.lix.db.selectFrom(\"file\").selectAll().execute();\n\n\t\texpect(files.length).toBe(\n\t\t\t5 + 1 /* the db.sqlite file */ + 1 /* project_id */\n\t\t);\n\n\t\tconst filesByPath = files.reduce((acc, file) => {\n\t\t\tacc[file.path] = new TextDecoder().decode(file.data);\n\t\t\treturn acc;\n\t\t}, {} as any);\n\n\t\texpect(filesByPath[\"/cache/plugin/29j49j2\"]).toBe(\"cache value\");\n\t\texpect(filesByPath[\"/.gitignore\"]).toBe(\"git value\");\n\t\texpect(filesByPath[\"/prettierrc.json\"]).toBe(\"prettier value\");\n\t\texpect(filesByPath[\"/README.md\"]).toBe(\"readme value\");\n\t\texpect(filesByPath[\"/settings.json\"]).toBe(JSON.stringify(mockSettings));\n\t});\n\n\ttest(\"file created in fs should be avaialable in lix \", async () => {\n\t\tconst syncInterval = 100;\n\t\tconst fs = Volume.fromJSON(mockDirectory);\n\n\t\tconst project = await loadProjectFromDirectory({\n\t\t\tfs: fs as any,\n\t\t\tpath: \"/project.inlang\",\n\t\t\tsyncInterval: syncInterval,\n\t\t});\n\n\t\tfs.writeFileSync(\n\t\t\t\"/project.inlang/file-created-on-fs.txt\",\n\t\t\t\"value written by fs\",\n\t\t\t{\n\t\t\t\tencoding: \"utf-8\",\n\t\t\t}\n\t\t);\n\n\t\t// lets wait a seconds to allow the sync process catch up\n\t\tawait new Promise((resolve) => setTimeout(resolve, syncInterval + 10));\n\n\t\tconst randomFileInLix = await project.lix.db\n\t\t\t.selectFrom(\"file\")\n\t\t\t.selectAll()\n\t\t\t.where(\"path\", \"=\", \"/file-created-on-fs.txt\")\n\t\t\t.executeTakeFirstOrThrow();\n\n\t\texpect(new TextDecoder().decode(randomFileInLix.data)).toBe(\n\t\t\t\"value written by fs\"\n\t\t);\n\t});\n\n\ttest(\"file updated in fs should be avaialable in lix \", async () => {\n\t\tconst syncInterval = 100;\n\t\tconst fs = Volume.fromJSON(mockDirectory);\n\n\t\tconst project = await loadProjectFromDirectory({\n\t\t\tfs: fs as any,\n\t\t\tpath: \"/project.inlang\",\n\t\t\tsyncInterval: syncInterval,\n\t\t});\n\n\t\t// \"changes to a file on disk should reflect in lix\n\t\tfs.writeFileSync(\n\t\t\t\"/project.inlang/settings.json\",\n\t\t\tJSON.stringify({\n\t\t\t\t...mockSettings,\n\t\t\t\tbaseLocale: \"brand-new-locale-written-to-fs-file\",\n\t\t\t})\n\t\t);\n\n\t\t// console.log(\"wrting fs settings\");\n\t\tawait new Promise((resolve) => setTimeout(resolve, syncInterval + 10));\n\t\tconst fileInLix = await project.lix.db\n\t\t\t.selectFrom(\"file\")\n\t\t\t.selectAll()\n\t\t\t.where(\"path\", \"=\", \"/settings.json\")\n\t\t\t.executeTakeFirstOrThrow();\n\n\t\tconst settingsAfterUpdateOnDisk = JSON.parse(\n\t\t\tnew TextDecoder().decode(fileInLix.data)\n\t\t);\n\n\t\texpect(settingsAfterUpdateOnDisk.baseLocale).toBe(\n\t\t\t\"brand-new-locale-written-to-fs-file\"\n\t\t);\n\t});\n\n\ttest(\"file deleted in fs should be droped from lix \", async () => {\n\t\tconst syncInterval = 100;\n\t\tconst fs = Volume.fromJSON(mockDirectory);\n\n\t\tconst project = await loadProjectFromDirectory({\n\t\t\tfs: fs as any,\n\t\t\tpath: \"/project.inlang\",\n\t\t\tsyncInterval: syncInterval,\n\t\t});\n\n\t\tconst filesInLixBefore = await project.lix.db\n\t\t\t.selectFrom(\"file\")\n\t\t\t.selectAll()\n\t\t\t.where(\"path\", \"=\", \"/README.md\")\n\t\t\t.execute();\n\n\t\texpect(filesInLixBefore.length).toBe(1);\n\n\t\t// \"changes to a file on disk should reflect in lix\n\t\tfs.unlinkSync(\"/project.inlang/README.md\");\n\n\t\t// console.log(\"wrting fs settings\");\n\t\tawait new Promise((resolve) => setTimeout(resolve, syncInterval + 10));\n\t\tconst fileInLixAfter = await project.lix.db\n\t\t\t.selectFrom(\"file\")\n\t\t\t.selectAll()\n\t\t\t.where(\"path\", \"=\", \"/README.md\")\n\t\t\t.execute();\n\n\t\texpect(fileInLixAfter.length).toBe(0);\n\t});\n\n\ttest(\"file created in lix should be avaialable in fs \", async () => {\n\t\tconst syncInterval = 100;\n\t\tconst fs = Volume.fromJSON(mockDirectory);\n\n\t\tconst project = await loadProjectFromDirectory({\n\t\t\tfs: fs as any,\n\t\t\tpath: \"/project.inlang\",\n\t\t\tsyncInterval: syncInterval,\n\t\t});\n\n\t\tawait project.lix.db\n\t\t\t.insertInto(\"file\")\n\t\t\t.values({\n\t\t\t\tpath: \"/file-created-in.lix.txt\",\n\t\t\t\tdata: new TextEncoder().encode(\"random value lix\"),\n\t\t\t})\n\t\t\t.execute();\n\n\t\t// lets wait a seconds to allow the sync process catch up\n\t\tawait new Promise((resolve) => setTimeout(resolve, syncInterval + 10));\n\n\t\tconst randomFileOnDiskContent = fs\n\t\t\t.readFileSync(\"/project.inlang/file-created-in.lix.txt\")\n\t\t\t.toString();\n\t\texpect(randomFileOnDiskContent).toBe(\"random value lix\");\n\t});\n\n\ttest(\"file updated in lix should be avaialable in fs \", async () => {\n\t\tconst syncInterval = 100;\n\t\tconst fs = Volume.fromJSON(mockDirectory);\n\n\t\tconst project = await loadProjectFromDirectory({\n\t\t\tfs: fs as any,\n\t\t\tpath: \"/project.inlang\",\n\t\t\tsyncInterval: syncInterval,\n\t\t});\n\n\t\t// console.log(\"wrting lix settings\");\n\t\t// changes to a file in lix should reflect in the project directory\n\t\tawait project.lix.db\n\t\t\t.updateTable(\"file\")\n\t\t\t.where(\"path\", \"=\", \"/settings.json\")\n\t\t\t.set({\n\t\t\t\tdata: new TextEncoder().encode(\n\t\t\t\t\tJSON.stringify({ ...mockSettings, baseLocale: \"brand-new-locale2\" })\n\t\t\t\t),\n\t\t\t})\n\t\t\t.execute();\n\n\t\t// lets wait a seconds to allow the sync process catch up\n\t\tawait new Promise((resolve) => setTimeout(resolve, syncInterval + 10));\n\n\t\tconst fileOnDisk = fs.readFileSync(\"/project.inlang/settings.json\");\n\t\tconst settings = JSON.parse(fileOnDisk.toString());\n\n\t\texpect(settings.baseLocale).toBe(\"brand-new-locale2\");\n\t});\n\n\ttest(\"file deleted in lix should be gone in fs as awell\", async () => {\n\t\tconst syncInterval = 100;\n\t\tconst fs = Volume.fromJSON(mockDirectory);\n\n\t\tconst project = await loadProjectFromDirectory({\n\t\t\tfs: fs as any,\n\t\t\tpath: \"/project.inlang\",\n\t\t\tsyncInterval: syncInterval,\n\t\t});\n\n\t\t// console.log(\"wrting lix settings\");\n\t\t// changes to a file in lix should reflect in the project directory\n\t\tawait project.lix.db\n\t\t\t.deleteFrom(\"file\")\n\t\t\t.where(\"path\", \"=\", \"/.gitignore\")\n\t\t\t.execute();\n\n\t\t// lets wait a seconds to allow the sync process catch up\n\t\tawait new Promise((resolve) => setTimeout(resolve, syncInterval + 10));\n\n\t\tconst fileExistsOnDisk = fs.existsSync(\"/project.inlang/.gitignore\");\n\n\t\texpect(fileExistsOnDisk).toBe(false);\n\t});\n\n\ttest(\"file updated in fs and lix (conflicting) should result in the fs state\", async () => {\n\t\tconst syncInterval = 100;\n\t\tconst fs = Volume.fromJSON(mockDirectory);\n\n\t\tconst project = await loadProjectFromDirectory({\n\t\t\tfs: fs as any,\n\t\t\tpath: \"/project.inlang\",\n\t\t\tsyncInterval: syncInterval,\n\t\t});\n\n\t\t// console.log(\"wrting fs settings simultanous\");\n\t\t// changes to a file on disk and lix at the same time should lead to the fs version\n\t\tfs.writeFileSync(\n\t\t\t\"/project.inlang/settings.json\",\n\t\t\tJSON.stringify({ ...mockSettings, baseLocale: \"fs-version\" })\n\t\t);\n\n\t\t// console.log(\"wrting lix settings simultanous\");\n\t\tawait project.lix.db\n\t\t\t.updateTable(\"file\")\n\t\t\t.where(\"path\", \"=\", \"/settings.json\")\n\t\t\t.set({\n\t\t\t\tdata: new TextEncoder().encode(\n\t\t\t\t\tJSON.stringify({ ...mockSettings, baseLocale: \"lix-version\" })\n\t\t\t\t),\n\t\t\t})\n\t\t\t.execute();\n\n\t\t// lets wait a seconds to allow the sync process catch up\n\t\tawait new Promise((resolve) => setTimeout(resolve, 1010));\n\n\t\tconst fileOnDiskUpdated = fs.readFileSync(\"/project.inlang/settings.json\");\n\t\tconst settingsUpdated = JSON.parse(fileOnDiskUpdated.toString());\n\n\t\texpect(settingsUpdated.baseLocale).toBe(\"fs-version\");\n\n\t\tconst fileInLixUpdated = await project.lix.db\n\t\t\t.selectFrom(\"file\")\n\t\t\t.selectAll()\n\t\t\t.where(\"path\", \"=\", \"/settings.json\")\n\t\t\t.executeTakeFirstOrThrow();\n\n\t\tconst settingsAfterUpdateOnDiskAndLix = JSON.parse(\n\t\t\tnew TextDecoder().decode(fileInLixUpdated.data)\n\t\t);\n\n\t\texpect(settingsAfterUpdateOnDiskAndLix.baseLocale).toBe(\"fs-version\");\n\t});\n});\n\ntest(\"errors from importing translation files should be shown\", async () => {\n\tconst mock = {\n\t\t\"/project.inlang/settings.json\": JSON.stringify({\n\t\t\tbaseLocale: \"en\",\n\t\t\tlocales: [\"en\", \"de\"],\n\t\t\tmodules: [],\n\t\t} satisfies ProjectSettings),\n\t};\n\n\tconst fs = Volume.fromJSON(mock);\n\n\tconst proxiedFs = new Proxy(fs, {\n\t\tget: (target, prop) => {\n\t\t\tif (prop === \"promises\") {\n\t\t\t\t// Intercept the 'promises' object\n\t\t\t\treturn new Proxy(target.promises, {\n\t\t\t\t\tget: (promisesTarget, promisesProp) => {\n\t\t\t\t\t\tif (promisesProp === \"readFile\") {\n\t\t\t\t\t\t\t// @ts-expect-error - we are mocking the fs\n\t\t\t\t\t\t\treturn (path, ...args) => {\n\t\t\t\t\t\t\t\tif (path.endsWith(\"some-file.json\")) {\n\t\t\t\t\t\t\t\t\tthrow new Error(\"MOCK ERROR\");\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\treturn promisesTarget.readFile(path, ...args);\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn Reflect.get(promisesTarget, promisesProp);\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn Reflect.get(target, prop);\n\t\t},\n\t});\n\n\tconst mockPlugin: InlangPlugin = {\n\t\tkey: \"mock-plugin\",\n\t\timportFiles: async () => {\n\t\t\treturn { bundles: [], messages: [], variants: [] };\n\t\t},\n\t\ttoBeImportedFiles: async () => {\n\t\t\treturn [{ path: \"./some-file.json\", locale: \"mock\" }];\n\t\t},\n\t};\n\n\tconst project = await loadProjectFromDirectory({\n\t\tfs: proxiedFs as any,\n\t\tpath: \"/project.inlang\",\n\t\tprovidePlugins: [mockPlugin],\n\t});\n\n\tconst errors = await project.errors.get();\n\t// TODO deactivated for now - we need to proxy fs.promises or change the signature of loadProject\n\texpect(errors).toHaveLength(1);\n\texpect(errors[0]).toBeInstanceOf(ResourceFileImportError);\n});\n\n// it happens often that a resource file doesn't exist yet on import\ntest(\"errors from importing translation files that are ENOENT should not be shown\", async () => {\n\tconst mock = {\n\t\t\"/project.inlang/settings.json\": JSON.stringify({\n\t\t\tbaseLocale: \"en\",\n\t\t\tlocales: [\"en\", \"de\"],\n\t\t\tmodules: [],\n\t\t} satisfies ProjectSettings),\n\t};\n\n\tconst fs = Volume.fromJSON(mock);\n\n\tconst mockPlugin: InlangPlugin = {\n\t\tkey: \"mock-plugin\",\n\t\timportFiles: async () => {\n\t\t\treturn { bundles: [], messages: [], variants: [] };\n\t\t},\n\t\ttoBeImportedFiles: async () => {\n\t\t\treturn [{ path: \"./some-non-existing-file.json\", locale: \"mock\" }];\n\t\t},\n\t};\n\n\tconst project = await loadProjectFromDirectory({\n\t\tfs: fs as any,\n\t\tpath: \"/project.inlang\",\n\t\tprovidePlugins: [mockPlugin],\n\t});\n\n\tconst errors = await project.errors.get();\n\texpect(errors).toHaveLength(0);\n});\n\n// it happens often that a resource file doesn't exist yet on import\ntest(\"it should pass toBeImportedMetadata on import\", async () => {\n\tconst mock = {\n\t\t\"/foo/en.json\": JSON.stringify({}),\n\t\t\"/project.inlang/settings.json\": JSON.stringify({\n\t\t\tbaseLocale: \"en\",\n\t\t\tlocales: [\"en\", \"de\"],\n\t\t} satisfies ProjectSettings),\n\t};\n\n\tconst fs = Volume.fromJSON(mock);\n\n\tconst mockPlugin: InlangPlugin = {\n\t\tkey: \"mock-plugin\",\n\t\ttoBeImportedFiles: async () => {\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\tpath: \"/foo/en.json\",\n\t\t\t\t\tlocale: \"mock\",\n\t\t\t\t\tmetadata: {\n\t\t\t\t\t\tfoo: \"bar\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t];\n\t\t},\n\t\timportFiles: async () => {\n\t\t\treturn { bundles: [], messages: [], variants: [] };\n\t\t},\n\t};\n\n\tconst toBeSpy = vi.spyOn(mockPlugin, \"toBeImportedFiles\");\n\tconst importSpy = vi.spyOn(mockPlugin, \"importFiles\");\n\n\tconst project = await loadProjectFromDirectory({\n\t\tfs: fs as any,\n\t\tpath: \"/project.inlang\",\n\t\tprovidePlugins: [mockPlugin],\n\t});\n\n\texpect(toBeSpy).toHaveBeenCalled();\n\n\texpect(importSpy).toHaveBeenCalledWith(\n\t\texpect.objectContaining({\n\t\t\tfiles: [\n\t\t\t\texpect.objectContaining({\n\t\t\t\t\tname: \"en.json\",\n\t\t\t\t\ttoBeImportedFilesMetadata: {\n\t\t\t\t\t\tfoo: \"bar\",\n\t\t\t\t\t},\n\t\t\t\t}),\n\t\t\t],\n\t\t})\n\t);\n});\n\ntest(\"it should provide plugins from disk for backwards compatibility but warn that those plugins are not portable\", async () => {\n\tconst mockRepo = {\n\t\t\"/local-plugins/mock-plugin.js\": \"export default { key: 'mock-plugin' }\",\n\t\t\"/local-plugins/mock-rule.js\":\n\t\t\t\"export default { id: 'messageLintRule.mock }\",\n\t\t\"/website/project.inlang/settings.json\": JSON.stringify({\n\t\t\tbaseLocale: \"en\",\n\t\t\tlocales: [\"en\", \"de\"],\n\t\t\tmodules: [\n\t\t\t\t\"../local-plugins/mock-plugin.js\",\n\t\t\t\t\"../local-plugins/mock-rule.js\",\n\t\t\t],\n\t\t} satisfies ProjectSettings),\n\t};\n\n\tconst fs = Volume.fromJSON(mockRepo);\n\n\tconst project = await loadProjectFromDirectory({\n\t\tfs: fs as any,\n\t\tpath: \"/website/project.inlang\",\n\t});\n\n\tconst plugins = await project.plugins.get();\n\tconst errors = await project.errors.get();\n\tconst settings = await project.settings.get();\n\n\texpect(plugins.length).toBe(1);\n\texpect(plugins[0]?.key).toBe(\"mock-plugin\");\n\n\texpect(errors.length).toBe(1);\n\texpect(errors[0]).toBeInstanceOf(WarningDeprecatedLintRule);\n\n\t// it should not remove the module from the settings\n\t// else roundtrips would not work\n\texpect(settings.modules?.[0]).toBe(\"../local-plugins/mock-plugin.js\");\n});\n\n// https://github.com/opral/inlang-sdk/issues/174\ntest(\"plugin calls that use fs should be intercepted to use an absolute path\", async () => {\n\tprocess.cwd = () => \"/\";\n\n\tconst mockRepo = {\n\t\t\"/messages/en.json\": JSON.stringify({\n\t\t\tkey1: \"value1\",\n\t\t\tkey2: \"value2\",\n\t\t}),\n\t\t\"/project.inlang/settings.json\": JSON.stringify({\n\t\t\tbaseLocale: \"en\",\n\t\t\tlocales: [\"en\", \"de\"],\n\t\t\t\"plugin.mock-plugin\": {\n\t\t\t\tpathPattern: \"./messages/{locale}.json\",\n\t\t\t},\n\t\t} satisfies ProjectSettings),\n\t};\n\n\tconst mockPlugin: InlangPlugin = {\n\t\tkey: \"mock-plugin\",\n\t\tloadMessages: async ({ nodeishFs, settings }) => {\n\t\t\tconst pathPattern = settings[\"plugin.mock-plugin\"]?.pathPattern.replace(\n\t\t\t\t\"{locale}\",\n\t\t\t\t\"en\"\n\t\t\t) as string;\n\t\t\tconst file = await nodeishFs.readFile(pathPattern);\n\t\t\t// reading the file should be possible without an error\n\t\t\texpect(file.toString()).toBe(\n\t\t\t\tJSON.stringify({\n\t\t\t\t\tkey1: \"value1\",\n\t\t\t\t\tkey2: \"value2\",\n\t\t\t\t})\n\t\t\t);\n\t\t\treturn [];\n\t\t},\n\t\tsaveMessages: async ({ nodeishFs, settings }) => {\n\t\t\tconst pathPattern = settings[\"plugin.mock-plugin\"]?.pathPattern.replace(\n\t\t\t\t\"{locale}\",\n\t\t\t\t\"en\"\n\t\t\t) as string;\n\t\t\tconst file = new TextEncoder().encode(\n\t\t\t\tJSON.stringify({\n\t\t\t\t\tkey1: \"value1\",\n\t\t\t\t\tkey2: \"value2\",\n\t\t\t\t\tkey3: \"value3\",\n\t\t\t\t})\n\t\t\t);\n\t\t\tawait nodeishFs.writeFile(pathPattern, file.buffer as ArrayBuffer);\n\t\t},\n\t\ttoBeImportedFiles: async ({ settings }) => {\n\t\t\tconst pathPattern = settings[\"plugin.mock-plugin\"]?.pathPattern.replace(\n\t\t\t\t\"{locale}\",\n\t\t\t\t\"en\"\n\t\t\t) as string;\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\tpath: pathPattern,\n\t\t\t\t\tlocale: \"en\",\n\t\t\t\t},\n\t\t\t];\n\t\t},\n\t};\n\n\tconst fs = Volume.fromJSON(mockRepo);\n\n\tconst loadMessagesSpy = vi.spyOn(mockPlugin, \"loadMessages\");\n\tconst saveMessagesSpy = vi.spyOn(mockPlugin, \"saveMessages\");\n\tconst toBeImportedFilesSpy = vi.spyOn(mockPlugin, \"toBeImportedFiles\");\n\tconst fsReadFileSpy = vi.spyOn(fs.promises, \"readFile\");\n\tconst fsWriteFileSpy = vi.spyOn(fs.promises, \"writeFile\");\n\n\tconst project = await loadProjectFromDirectory({\n\t\tfs: fs as any,\n\t\tpath: \"/project.inlang\",\n\t\tprovidePlugins: [mockPlugin],\n\t});\n\n\texpect(loadMessagesSpy).toHaveBeenCalled();\n\texpect(fsReadFileSpy).toHaveBeenCalledWith(\"/messages/en.json\", undefined);\n\n\t// todo test that saveMessages works too.\n\t// await project.db.insertInto(\"bundle\").defaultValues().execute();\n\n\t// const translationFile = await fs.readFile(\"/messages/en.json\", \"utf-8\");\n\n\t// expect(translationFile).toBe(\n\t// \tJSON.stringify({\n\t// \t\tkey1: \"value1\",\n\t// \t\tkey2: \"value2\",\n\t// \t\tkey3: \"value3\",\n\t// \t})\n\t// );\n\n\t// expect(fsWriteFileSpy).toHaveBeenCalledWith(\n\t// \t\"/messages/en.json\",\n\t// \tJSON.stringify({\n\t// \t\tkey1: \"value1\",\n\t// \t\tkey2: \"value2\",\n\t// \t\tkey3: \"value3\",\n\t// \t}),\n\t// \t\"utf-8\"\n\t// );\n\n\t// expect(saveMessagesSpy).toHaveBeenCalled();\n\t// expect(toBeImportedFilesSpy).toHaveBeenCalled();\n});\n\ntest(\"it can import plugins via http\", async () => {\n\tconst mockRepo = {\n\t\t\"/project.inlang/settings.json\": JSON.stringify({\n\t\t\tbaseLocale: \"en\",\n\t\t\tlocales: [\"en\"],\n\t\t\tmodules: [\"https://example.com/plugin.js\"],\n\t\t} satisfies ProjectSettings),\n\t};\n\n\tconst fs = Volume.fromJSON(mockRepo);\n\n\tconst mockPluginModule = `export default {\n\t\t\tkey: \"mock-plugin\"\t\n\t\t}`;\n\n\tglobal.fetch = vi.fn(() => Promise.resolve(new Response(mockPluginModule)));\n\n\tconst project = await loadProjectFromDirectory({\n\t\tfs: fs as any,\n\t\tpath: \"/project.inlang\",\n\t});\n\n\tconst plugins = await project.plugins.get();\n\n\texpect(global.fetch).toHaveBeenCalledWith(\"https://example.com/plugin.js\");\n\texpect(plugins.length).toBe(1);\n\n\tconst pluginCache = await project.lix.db\n\t\t.selectFrom(\"file\")\n\t\t.selectAll()\n\t\t.where(\"path\", \"like\", \"/cache/plugins/%\")\n\t\t.execute();\n\n\texpect(\n\t\tpluginCache.some(\n\t\t\t(file) => new TextDecoder().decode(file.data) === mockPluginModule\n\t\t),\n\t\t\"expecting the plugin to be cached\"\n\t).toBe(true);\n});\n"],"names":[],"mappings":"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","debug_id":"f4f0657b-efd6-57ad-929c-9ac84897bf71"}
|
|
1
|
+
{"version":3,"file":"loadProjectFromDirectory.test.js","sources":["project/loadProjectFromDirectory.test.ts"],"sourceRoot":"/","sourcesContent":["/* eslint-disable @typescript-eslint/no-unused-vars */\n\nimport { beforeEach, describe, expect, test, vi } from \"vitest\";\nimport { ProjectSettings } from \"../json-schema/settings.js\";\nimport { fs, vol, Volume } from \"memfs\";\nimport {\n\tloadProjectFromDirectory,\n\tResourceFileImportError,\n\tWarningDeprecatedLintRule,\n} from \"./loadProjectFromDirectory.js\";\nimport { selectBundleNested } from \"../query-utilities/selectBundleNested.js\";\nimport { Text } from \"../json-schema/pattern.js\";\nimport type { InlangPlugin } from \"../plugin/schema.js\";\nimport type {\n\tMessageV1,\n\tVariantV1,\n} from \"../json-schema/old-v1-message/schemaV1.js\";\nimport { saveProjectToDirectory } from \"./saveProjectToDirectory.js\";\nimport { insertBundleNested } from \"../query-utilities/insertBundleNested.js\";\n\ntest(\"plugin.loadMessages and plugin.saveMessages must not be configured together with import export\", async () => {\n\tconst mockLegacyPlugin: InlangPlugin = {\n\t\tkey: \"mock-legacy-plugin\",\n\t\tloadMessages: async () => {\n\t\t\treturn [];\n\t\t},\n\t\tsaveMessages: async () => {},\n\t};\n\n\tconst mockLegacyPlugin2: InlangPlugin = {\n\t\tkey: \"mock-legacy-plugin-2\",\n\t\tloadMessages: async () => {\n\t\t\treturn [];\n\t\t},\n\t\tsaveMessages: async () => {},\n\t};\n\n\tconst mockImportExportPlugin: InlangPlugin = {\n\t\tkey: \"mock-import-export-plugin\",\n\t\texportFiles: () => {\n\t\t\treturn [];\n\t\t},\n\t\timportFiles: () => {\n\t\t\treturn {} as any;\n\t\t},\n\t};\n\n\tawait expect(\n\t\t(async () => {\n\t\t\tawait loadProjectFromDirectory({\n\t\t\t\tfs: Volume.fromJSON({\n\t\t\t\t\t\"./project.inlang/settings.json\": JSON.stringify({\n\t\t\t\t\t\tbaseLocale: \"en\",\n\t\t\t\t\t\tlocales: [\"en\", \"de\"],\n\t\t\t\t\t\tmodules: [],\n\t\t\t\t\t} satisfies ProjectSettings),\n\t\t\t\t}) as any,\n\t\t\t\tpath: \"./project.inlang\",\n\t\t\t\tprovidePlugins: [\n\t\t\t\t\tmockLegacyPlugin,\n\t\t\t\t\tmockLegacyPlugin2,\n\t\t\t\t\tmockImportExportPlugin,\n\t\t\t\t],\n\t\t\t});\n\t\t})()\n\t).rejects.toThrowError();\n\n\tawait expect(\n\t\t(async () => {\n\t\t\tawait loadProjectFromDirectory({\n\t\t\t\tfs: Volume.fromJSON({\n\t\t\t\t\t\"./project.inlang/settings.json\": JSON.stringify({\n\t\t\t\t\t\tbaseLocale: \"en\",\n\t\t\t\t\t\tlocales: [\"en\", \"de\"],\n\t\t\t\t\t\tmodules: [],\n\t\t\t\t\t} satisfies ProjectSettings),\n\t\t\t\t}) as any,\n\t\t\t\tpath: \"./project.inlang\",\n\t\t\t\tprovidePlugins: [\n\t\t\t\t\tmockLegacyPlugin,\n\t\t\t\t\tmockLegacyPlugin2,\n\t\t\t\t\tmockImportExportPlugin,\n\t\t\t\t],\n\t\t\t});\n\t\t})()\n\t).rejects.toThrowError();\n});\n\ntest(\"plugin.loadMessages and plugin.saveMessages should work for legacy purposes\", async () => {\n\tconst mockLegacyPlugin: InlangPlugin = {\n\t\tid: \"mock-legacy-plugin\",\n\t\t// @ts-expect-error - id is deprecated, key can be undefined\n\t\tkey: undefined,\n\t\tloadMessages: async ({ nodeishFs, settings }) => {\n\t\t\tconst pathPattern = settings[\"plugin.mock-plugin\"]?.pathPattern as string;\n\n\t\t\tconst messages: MessageV1[] = [];\n\n\t\t\t// @ts-expect-error - language tag is always given by the sdk v2\n\t\t\tfor (const languageTag of settings.languageTags) {\n\t\t\t\tconst data = await nodeishFs.readFile(\n\t\t\t\t\tpathPattern.replace(\"{languageTag}\", languageTag)\n\t\t\t\t);\n\n\t\t\t\tfor (const [key, value] of Object.entries(\n\t\t\t\t\tJSON.parse(data.toString())\n\t\t\t\t)) {\n\t\t\t\t\tconst exisitngMessage = messages.find(\n\t\t\t\t\t\t(message) => message.id === key\n\t\t\t\t\t);\n\t\t\t\t\tconst variant = {\n\t\t\t\t\t\tlanguageTag: languageTag,\n\t\t\t\t\t\tmatch: [],\n\t\t\t\t\t\tpattern: [{ type: \"Text\", value: value }],\n\t\t\t\t\t} as VariantV1;\n\t\t\t\t\tif (exisitngMessage !== undefined) {\n\t\t\t\t\t\texisitngMessage.variants.push(variant);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tmessages.push({\n\t\t\t\t\t\t\talias: {},\n\t\t\t\t\t\t\tid: key,\n\t\t\t\t\t\t\tselectors: [],\n\t\t\t\t\t\t\tvariants: [variant],\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn messages;\n\t\t},\n\t\tsaveMessages: async ({ messages, nodeishFs, settings }) => {\n\t\t\tconst pathPattern = settings[\"plugin.mock-plugin\"]?.pathPattern as string;\n\t\t\tfor (const languageTag of settings.languageTags!) {\n\t\t\t\tconst messagesInLanguage = {} as Record<string, string>;\n\t\t\t\tfor (const message of messages) {\n\t\t\t\t\tconst variantsInLanguage = message.variants.filter(\n\t\t\t\t\t\t(variant) => variant.languageTag === languageTag\n\t\t\t\t\t);\n\t\t\t\t\tif (variantsInLanguage.length > 1) {\n\t\t\t\t\t\t// data will get lost during export => throw?\n\t\t\t\t\t} else if (variantsInLanguage.length === 1) {\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\tvariantsInLanguage[0]!.pattern.length != 1 ||\n\t\t\t\t\t\t\tvariantsInLanguage[0]!.pattern[0]?.type !== \"Text\"\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t// throw?\n\t\t\t\t\t\t}\n\t\t\t\t\t\tmessagesInLanguage[message.id] = (\n\t\t\t\t\t\t\tvariantsInLanguage[0]!.pattern[0]! as any\n\t\t\t\t\t\t).value;\n\t\t\t\t\t}\n\t\t\t\t\t// else no-op\n\t\t\t\t}\n\t\t\t\tawait nodeishFs.writeFile(\n\t\t\t\t\tpathPattern.replace(\"{languageTag}\", languageTag),\n\t\t\t\t\tJSON.stringify(messagesInLanguage, null, 2)\n\t\t\t\t);\n\t\t\t}\n\t\t},\n\t};\n\tconst mockRepo = {\n\t\t\"./README.md\": \"# Hello World\",\n\t\t\"./src/index.js\": \"console.log('Hello World')\",\n\t\t\"./src/translations/en.json\": JSON.stringify({\n\t\t\tkey1: \"value1\",\n\t\t\tkey2: \"value2\",\n\t\t}),\n\t\t\"./src/translations/de.json\": JSON.stringify({\n\t\t\tkey1: \"wert1\",\n\t\t\tkey2: \"wert2\",\n\t\t}),\n\t\t\"./project.inlang/settings.json\": JSON.stringify({\n\t\t\tbaseLocale: \"en\",\n\t\t\tlocales: [\"en\", \"de\"],\n\t\t\tmodules: [\"./mock-module.js\"],\n\t\t\t\"plugin.mock-plugin\": {\n\t\t\t\tpathPattern: \"./src/translations/{languageTag}.json\",\n\t\t\t},\n\t\t} satisfies ProjectSettings),\n\t};\n\n\tconst fs = Volume.fromJSON(mockRepo);\n\n\tlet project = await loadProjectFromDirectory({\n\t\tfs: fs as any,\n\t\tpath: \"./project.inlang\",\n\t\tprovidePlugins: [mockLegacyPlugin],\n\t});\n\n\tawait insertBundleNested(project.db, {\n\t\tid: \"key-id\",\n\t\tmessages: [\n\t\t\t{\n\t\t\t\tid: \"mock-message\",\n\t\t\t\tbundleId: \"mock-bundle\",\n\t\t\t\tlocale: \"en\",\n\t\t\t\tselectors: [],\n\t\t\t\tvariants: [\n\t\t\t\t\t{\n\t\t\t\t\t\tmessageId: \"mock-message\",\n\t\t\t\t\t\tpattern: [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\ttype: \"text\",\n\t\t\t\t\t\t\t\tvalue: \"JOJO\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t],\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t},\n\t\t],\n\t});\n\n\tawait saveProjectToDirectory({\n\t\tfs: fs.promises as any,\n\t\tpath: \"./project.inlang\",\n\t\tproject,\n\t});\n\n\tproject = await loadProjectFromDirectory({\n\t\tfs: fs as any,\n\t\tpath: \"./project.inlang\",\n\t\tprovidePlugins: [mockLegacyPlugin],\n\t});\n\n\tconst bundles = await selectBundleNested(project.db).execute();\n\n\tconst bundlesOrdered = bundles.sort((a, b) => a.id.localeCompare(b.id));\n\n\texpect(bundles.length).toBe(3);\n\texpect(bundlesOrdered[0]?.messages[0]?.locale).toBe(\"en\");\n\texpect(\n\t\t(bundlesOrdered[0]?.messages[0]?.variants[0]?.pattern[0] as Text)?.value\n\t).toBe(\"JOJO\");\n\n\t// TODO fix\n\t// expect(bundlesOrdered[0]?.messages[9]?.locale).toBe(\"en\");\n\t// expect(\n\t// \t(bundlesOrdered[0]?.messages[1]?.variants[0]?.pattern[0] as Text)?.value\n\t// ).toBe(\"wert1\");\n\n\t// expect(bundlesOrdered[1]?.messages[0]?.locale).toBe(\"en\");\n\t// expect(\n\t// \t(bundlesOrdered[1]?.messages[0]?.variants[0]?.pattern[0] as Text)?.value\n\t// ).toBe(\"value2\");\n\n\t// expect(bundlesOrdered[1]?.messages[1]?.locale).toBe(\"de\");\n\t// expect(\n\t// \t(bundlesOrdered[1]?.messages[1]?.variants[0]?.pattern[0] as Text)?.value\n\t// ).toBe(\"wert2\");\n});\n\nconst mockSettings = {\n\tbaseLocale: \"en\",\n\tlocales: [\"en\", \"de\"],\n\tmodules: [],\n} satisfies ProjectSettings;\n\nconst mockDirectory = {\n\t\"/project.inlang/cache/plugin/29j49j2\": \"cache value\",\n\t\"/project.inlang/.gitignore\": \"git value\",\n\t\"/project.inlang/prettierrc.json\": \"prettier value\",\n\t\"/project.inlang/README.md\": \"readme value\",\n\t\"/project.inlang/settings.json\": JSON.stringify(mockSettings),\n};\n\ndescribe(\"it should keep files between the inlang directory and lix in sync\", async () => {\n\ttest(\"files from directory should be available via lix after project has been loaded from directory\", async () => {\n\t\tconst syncInterval = 100;\n\t\tconst fs = Volume.fromJSON(mockDirectory);\n\n\t\tconst project = await loadProjectFromDirectory({\n\t\t\tfs: fs as any,\n\t\t\tpath: \"/project.inlang\",\n\t\t\tsyncInterval: syncInterval,\n\t\t});\n\n\t\tconst files = await project.lix.db.selectFrom(\"file\").selectAll().execute();\n\n\t\texpect(files.length).toBe(\n\t\t\t5 + 1 /* the db.sqlite file */ + 1 /* project_id */\n\t\t);\n\n\t\tconst filesByPath = files.reduce((acc, file) => {\n\t\t\tacc[file.path] = new TextDecoder().decode(file.data);\n\t\t\treturn acc;\n\t\t}, {} as any);\n\n\t\texpect(filesByPath[\"/cache/plugin/29j49j2\"]).toBe(\"cache value\");\n\t\texpect(filesByPath[\"/.gitignore\"]).toBe(\"git value\");\n\t\texpect(filesByPath[\"/prettierrc.json\"]).toBe(\"prettier value\");\n\t\texpect(filesByPath[\"/README.md\"]).toBe(\"readme value\");\n\t\texpect(filesByPath[\"/settings.json\"]).toBe(JSON.stringify(mockSettings));\n\t});\n\n\ttest(\"file created in fs should be avaialable in lix \", async () => {\n\t\tconst syncInterval = 100;\n\t\tconst fs = Volume.fromJSON(mockDirectory);\n\n\t\tconst project = await loadProjectFromDirectory({\n\t\t\tfs: fs as any,\n\t\t\tpath: \"/project.inlang\",\n\t\t\tsyncInterval: syncInterval,\n\t\t});\n\n\t\tfs.writeFileSync(\n\t\t\t\"/project.inlang/file-created-on-fs.txt\",\n\t\t\t\"value written by fs\",\n\t\t\t{\n\t\t\t\tencoding: \"utf-8\",\n\t\t\t}\n\t\t);\n\n\t\t// lets wait a seconds to allow the sync process catch up\n\t\tawait new Promise((resolve) => setTimeout(resolve, syncInterval + 10));\n\n\t\tconst randomFileInLix = await project.lix.db\n\t\t\t.selectFrom(\"file\")\n\t\t\t.selectAll()\n\t\t\t.where(\"path\", \"=\", \"/file-created-on-fs.txt\")\n\t\t\t.executeTakeFirstOrThrow();\n\n\t\texpect(new TextDecoder().decode(randomFileInLix.data)).toBe(\n\t\t\t\"value written by fs\"\n\t\t);\n\t});\n\n\ttest(\"file updated in fs should be avaialable in lix \", async () => {\n\t\tconst syncInterval = 100;\n\t\tconst fs = Volume.fromJSON(mockDirectory);\n\n\t\tconst project = await loadProjectFromDirectory({\n\t\t\tfs: fs as any,\n\t\t\tpath: \"/project.inlang\",\n\t\t\tsyncInterval: syncInterval,\n\t\t});\n\n\t\t// \"changes to a file on disk should reflect in lix\n\t\tfs.writeFileSync(\n\t\t\t\"/project.inlang/settings.json\",\n\t\t\tJSON.stringify({\n\t\t\t\t...mockSettings,\n\t\t\t\tbaseLocale: \"brand-new-locale-written-to-fs-file\",\n\t\t\t})\n\t\t);\n\n\t\t// console.log(\"wrting fs settings\");\n\t\tawait new Promise((resolve) => setTimeout(resolve, syncInterval + 10));\n\t\tconst fileInLix = await project.lix.db\n\t\t\t.selectFrom(\"file\")\n\t\t\t.selectAll()\n\t\t\t.where(\"path\", \"=\", \"/settings.json\")\n\t\t\t.executeTakeFirstOrThrow();\n\n\t\tconst settingsAfterUpdateOnDisk = JSON.parse(\n\t\t\tnew TextDecoder().decode(fileInLix.data)\n\t\t);\n\n\t\texpect(settingsAfterUpdateOnDisk.baseLocale).toBe(\n\t\t\t\"brand-new-locale-written-to-fs-file\"\n\t\t);\n\t});\n\n\ttest(\"file deleted in fs should be droped from lix \", async () => {\n\t\tconst syncInterval = 100;\n\t\tconst fs = Volume.fromJSON(mockDirectory);\n\n\t\tconst project = await loadProjectFromDirectory({\n\t\t\tfs: fs as any,\n\t\t\tpath: \"/project.inlang\",\n\t\t\tsyncInterval: syncInterval,\n\t\t});\n\n\t\tconst filesInLixBefore = await project.lix.db\n\t\t\t.selectFrom(\"file\")\n\t\t\t.selectAll()\n\t\t\t.where(\"path\", \"=\", \"/README.md\")\n\t\t\t.execute();\n\n\t\texpect(filesInLixBefore.length).toBe(1);\n\n\t\t// \"changes to a file on disk should reflect in lix\n\t\tfs.unlinkSync(\"/project.inlang/README.md\");\n\n\t\t// console.log(\"wrting fs settings\");\n\t\tawait new Promise((resolve) => setTimeout(resolve, syncInterval + 10));\n\t\tconst fileInLixAfter = await project.lix.db\n\t\t\t.selectFrom(\"file\")\n\t\t\t.selectAll()\n\t\t\t.where(\"path\", \"=\", \"/README.md\")\n\t\t\t.execute();\n\n\t\texpect(fileInLixAfter.length).toBe(0);\n\t});\n\n\ttest(\"file created in lix should be avaialable in fs \", async () => {\n\t\tconst syncInterval = 100;\n\t\tconst fs = Volume.fromJSON(mockDirectory);\n\n\t\tconst project = await loadProjectFromDirectory({\n\t\t\tfs: fs as any,\n\t\t\tpath: \"/project.inlang\",\n\t\t\tsyncInterval: syncInterval,\n\t\t});\n\n\t\tawait project.lix.db\n\t\t\t.insertInto(\"file\")\n\t\t\t.values({\n\t\t\t\tpath: \"/file-created-in.lix.txt\",\n\t\t\t\tdata: new TextEncoder().encode(\"random value lix\"),\n\t\t\t})\n\t\t\t.execute();\n\n\t\t// lets wait a seconds to allow the sync process catch up\n\t\tawait new Promise((resolve) => setTimeout(resolve, syncInterval + 10));\n\n\t\tconst randomFileOnDiskContent = fs\n\t\t\t.readFileSync(\"/project.inlang/file-created-in.lix.txt\")\n\t\t\t.toString();\n\t\texpect(randomFileOnDiskContent).toBe(\"random value lix\");\n\t});\n\n\ttest(\"file updated in lix should be avaialable in fs \", async () => {\n\t\tconst syncInterval = 100;\n\t\tconst fs = Volume.fromJSON(mockDirectory);\n\n\t\tconst project = await loadProjectFromDirectory({\n\t\t\tfs: fs as any,\n\t\t\tpath: \"/project.inlang\",\n\t\t\tsyncInterval: syncInterval,\n\t\t});\n\n\t\t// console.log(\"wrting lix settings\");\n\t\t// changes to a file in lix should reflect in the project directory\n\t\tawait project.lix.db\n\t\t\t.updateTable(\"file\")\n\t\t\t.where(\"path\", \"=\", \"/settings.json\")\n\t\t\t.set({\n\t\t\t\tdata: new TextEncoder().encode(\n\t\t\t\t\tJSON.stringify({ ...mockSettings, baseLocale: \"brand-new-locale2\" })\n\t\t\t\t),\n\t\t\t})\n\t\t\t.execute();\n\n\t\t// lets wait a seconds to allow the sync process catch up\n\t\tawait new Promise((resolve) => setTimeout(resolve, syncInterval + 10));\n\n\t\tconst fileOnDisk = fs.readFileSync(\"/project.inlang/settings.json\");\n\t\tconst settings = JSON.parse(fileOnDisk.toString());\n\n\t\texpect(settings.baseLocale).toBe(\"brand-new-locale2\");\n\t});\n\n\ttest(\"file deleted in lix should be gone in fs as awell\", async () => {\n\t\tconst syncInterval = 100;\n\t\tconst fs = Volume.fromJSON(mockDirectory);\n\n\t\tconst project = await loadProjectFromDirectory({\n\t\t\tfs: fs as any,\n\t\t\tpath: \"/project.inlang\",\n\t\t\tsyncInterval: syncInterval,\n\t\t});\n\n\t\t// console.log(\"wrting lix settings\");\n\t\t// changes to a file in lix should reflect in the project directory\n\t\tawait project.lix.db\n\t\t\t.deleteFrom(\"file\")\n\t\t\t.where(\"path\", \"=\", \"/.gitignore\")\n\t\t\t.execute();\n\n\t\t// lets wait a seconds to allow the sync process catch up\n\t\tawait new Promise((resolve) => setTimeout(resolve, syncInterval + 10));\n\n\t\tconst fileExistsOnDisk = fs.existsSync(\"/project.inlang/.gitignore\");\n\n\t\texpect(fileExistsOnDisk).toBe(false);\n\t});\n\n\ttest(\"file updated in fs and lix (conflicting) should result in the fs state\", async () => {\n\t\tconst syncInterval = 100;\n\t\tconst fs = Volume.fromJSON(mockDirectory);\n\n\t\tconst project = await loadProjectFromDirectory({\n\t\t\tfs: fs as any,\n\t\t\tpath: \"/project.inlang\",\n\t\t\tsyncInterval: syncInterval,\n\t\t});\n\n\t\t// console.log(\"wrting fs settings simultanous\");\n\t\t// changes to a file on disk and lix at the same time should lead to the fs version\n\t\tfs.writeFileSync(\n\t\t\t\"/project.inlang/settings.json\",\n\t\t\tJSON.stringify({ ...mockSettings, baseLocale: \"fs-version\" })\n\t\t);\n\n\t\t// console.log(\"wrting lix settings simultanous\");\n\t\tawait project.lix.db\n\t\t\t.updateTable(\"file\")\n\t\t\t.where(\"path\", \"=\", \"/settings.json\")\n\t\t\t.set({\n\t\t\t\tdata: new TextEncoder().encode(\n\t\t\t\t\tJSON.stringify({ ...mockSettings, baseLocale: \"lix-version\" })\n\t\t\t\t),\n\t\t\t})\n\t\t\t.execute();\n\n\t\t// lets wait a seconds to allow the sync process catch up\n\t\tawait new Promise((resolve) => setTimeout(resolve, 1010));\n\n\t\tconst fileOnDiskUpdated = fs.readFileSync(\"/project.inlang/settings.json\");\n\t\tconst settingsUpdated = JSON.parse(fileOnDiskUpdated.toString());\n\n\t\texpect(settingsUpdated.baseLocale).toBe(\"fs-version\");\n\n\t\tconst fileInLixUpdated = await project.lix.db\n\t\t\t.selectFrom(\"file\")\n\t\t\t.selectAll()\n\t\t\t.where(\"path\", \"=\", \"/settings.json\")\n\t\t\t.executeTakeFirstOrThrow();\n\n\t\tconst settingsAfterUpdateOnDiskAndLix = JSON.parse(\n\t\t\tnew TextDecoder().decode(fileInLixUpdated.data)\n\t\t);\n\n\t\texpect(settingsAfterUpdateOnDiskAndLix.baseLocale).toBe(\"fs-version\");\n\t});\n});\n\ntest(\"errors from importing translation files should be shown\", async () => {\n\tconst mock = {\n\t\t\"/project.inlang/settings.json\": JSON.stringify({\n\t\t\tbaseLocale: \"en\",\n\t\t\tlocales: [\"en\", \"de\"],\n\t\t\tmodules: [],\n\t\t} satisfies ProjectSettings),\n\t};\n\n\tconst fs = Volume.fromJSON(mock);\n\n\tconst proxiedFs = new Proxy(fs, {\n\t\tget: (target, prop) => {\n\t\t\tif (prop === \"promises\") {\n\t\t\t\t// Intercept the 'promises' object\n\t\t\t\treturn new Proxy(target.promises, {\n\t\t\t\t\tget: (promisesTarget, promisesProp) => {\n\t\t\t\t\t\tif (promisesProp === \"readFile\") {\n\t\t\t\t\t\t\t// @ts-expect-error - we are mocking the fs\n\t\t\t\t\t\t\treturn (path, ...args) => {\n\t\t\t\t\t\t\t\tif (path.endsWith(\"some-file.json\")) {\n\t\t\t\t\t\t\t\t\tthrow new Error(\"MOCK ERROR\");\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\treturn promisesTarget.readFile(path, ...args);\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn Reflect.get(promisesTarget, promisesProp);\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn Reflect.get(target, prop);\n\t\t},\n\t});\n\n\tconst mockPlugin: InlangPlugin = {\n\t\tkey: \"mock-plugin\",\n\t\timportFiles: async () => {\n\t\t\treturn { bundles: [], messages: [], variants: [] };\n\t\t},\n\t\ttoBeImportedFiles: async () => {\n\t\t\treturn [{ path: \"./some-file.json\", locale: \"mock\" }];\n\t\t},\n\t};\n\n\tconst project = await loadProjectFromDirectory({\n\t\tfs: proxiedFs as any,\n\t\tpath: \"/project.inlang\",\n\t\tprovidePlugins: [mockPlugin],\n\t});\n\n\tconst errors = await project.errors.get();\n\t// TODO deactivated for now - we need to proxy fs.promises or change the signature of loadProject\n\texpect(errors).toHaveLength(1);\n\texpect(errors[0]).toBeInstanceOf(ResourceFileImportError);\n});\n\n// it happens often that a resource file doesn't exist yet on import\ntest(\"errors from importing translation files that are ENOENT should not be shown\", async () => {\n\tconst mock = {\n\t\t\"/project.inlang/settings.json\": JSON.stringify({\n\t\t\tbaseLocale: \"en\",\n\t\t\tlocales: [\"en\", \"de\"],\n\t\t\tmodules: [],\n\t\t} satisfies ProjectSettings),\n\t};\n\n\tconst fs = Volume.fromJSON(mock);\n\n\tconst mockPlugin: InlangPlugin = {\n\t\tkey: \"mock-plugin\",\n\t\timportFiles: async () => {\n\t\t\treturn { bundles: [], messages: [], variants: [] };\n\t\t},\n\t\ttoBeImportedFiles: async () => {\n\t\t\treturn [{ path: \"./some-non-existing-file.json\", locale: \"mock\" }];\n\t\t},\n\t};\n\n\tconst project = await loadProjectFromDirectory({\n\t\tfs: fs as any,\n\t\tpath: \"/project.inlang\",\n\t\tprovidePlugins: [mockPlugin],\n\t});\n\n\tconst errors = await project.errors.get();\n\texpect(errors).toHaveLength(0);\n});\n\n// it happens often that a resource file doesn't exist yet on import\ntest(\"it should pass toBeImportedMetadata on import\", async () => {\n\tconst mock = {\n\t\t\"/foo/en.json\": JSON.stringify({}),\n\t\t\"/project.inlang/settings.json\": JSON.stringify({\n\t\t\tbaseLocale: \"en\",\n\t\t\tlocales: [\"en\", \"de\"],\n\t\t} satisfies ProjectSettings),\n\t};\n\n\tconst fs = Volume.fromJSON(mock);\n\n\tconst mockPlugin: InlangPlugin = {\n\t\tkey: \"mock-plugin\",\n\t\ttoBeImportedFiles: async () => {\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\tpath: \"/foo/en.json\",\n\t\t\t\t\tlocale: \"mock\",\n\t\t\t\t\tmetadata: {\n\t\t\t\t\t\tfoo: \"bar\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t];\n\t\t},\n\t\timportFiles: async () => {\n\t\t\treturn { bundles: [], messages: [], variants: [] };\n\t\t},\n\t};\n\n\tconst toBeSpy = vi.spyOn(mockPlugin, \"toBeImportedFiles\");\n\tconst importSpy = vi.spyOn(mockPlugin, \"importFiles\");\n\n\tconst project = await loadProjectFromDirectory({\n\t\tfs: fs as any,\n\t\tpath: \"/project.inlang\",\n\t\tprovidePlugins: [mockPlugin],\n\t});\n\n\texpect(toBeSpy).toHaveBeenCalled();\n\n\texpect(importSpy).toHaveBeenCalledWith(\n\t\texpect.objectContaining({\n\t\t\tfiles: [\n\t\t\t\texpect.objectContaining({\n\t\t\t\t\ttoBeImportedFilesMetadata: {\n\t\t\t\t\t\tfoo: \"bar\",\n\t\t\t\t\t},\n\t\t\t\t}),\n\t\t\t],\n\t\t})\n\t);\n});\n\ntest(\"it should provide plugins from disk for backwards compatibility but warn that those plugins are not portable\", async () => {\n\tconst mockRepo = {\n\t\t\"/local-plugins/mock-plugin.js\": \"export default { key: 'mock-plugin' }\",\n\t\t\"/local-plugins/mock-rule.js\":\n\t\t\t\"export default { id: 'messageLintRule.mock }\",\n\t\t\"/website/project.inlang/settings.json\": JSON.stringify({\n\t\t\tbaseLocale: \"en\",\n\t\t\tlocales: [\"en\", \"de\"],\n\t\t\tmodules: [\n\t\t\t\t\"../local-plugins/mock-plugin.js\",\n\t\t\t\t\"../local-plugins/mock-rule.js\",\n\t\t\t],\n\t\t} satisfies ProjectSettings),\n\t};\n\n\tconst fs = Volume.fromJSON(mockRepo);\n\n\tconst project = await loadProjectFromDirectory({\n\t\tfs: fs as any,\n\t\tpath: \"/website/project.inlang\",\n\t});\n\n\tconst plugins = await project.plugins.get();\n\tconst errors = await project.errors.get();\n\tconst settings = await project.settings.get();\n\n\texpect(plugins.length).toBe(1);\n\texpect(plugins[0]?.key).toBe(\"mock-plugin\");\n\n\texpect(errors.length).toBe(1);\n\texpect(errors[0]).toBeInstanceOf(WarningDeprecatedLintRule);\n\n\t// it should not remove the module from the settings\n\t// else roundtrips would not work\n\texpect(settings.modules?.[0]).toBe(\"../local-plugins/mock-plugin.js\");\n});\n\n// https://github.com/opral/inlang-sdk/issues/174\ntest(\"plugin calls that use fs should be intercepted to use an absolute path\", async () => {\n\tprocess.cwd = () => \"/\";\n\n\tconst mockRepo = {\n\t\t\"/messages/en.json\": JSON.stringify({\n\t\t\tkey1: \"value1\",\n\t\t\tkey2: \"value2\",\n\t\t}),\n\t\t\"/project.inlang/settings.json\": JSON.stringify({\n\t\t\tbaseLocale: \"en\",\n\t\t\tlocales: [\"en\", \"de\"],\n\t\t\t\"plugin.mock-plugin\": {\n\t\t\t\tpathPattern: \"./messages/{locale}.json\",\n\t\t\t},\n\t\t} satisfies ProjectSettings),\n\t};\n\n\tconst mockPlugin: InlangPlugin = {\n\t\tkey: \"mock-plugin\",\n\t\tloadMessages: async ({ nodeishFs, settings }) => {\n\t\t\tconst pathPattern = settings[\"plugin.mock-plugin\"]?.pathPattern.replace(\n\t\t\t\t\"{locale}\",\n\t\t\t\t\"en\"\n\t\t\t) as string;\n\t\t\tconst file = await nodeishFs.readFile(pathPattern);\n\t\t\t// reading the file should be possible without an error\n\t\t\texpect(file.toString()).toBe(\n\t\t\t\tJSON.stringify({\n\t\t\t\t\tkey1: \"value1\",\n\t\t\t\t\tkey2: \"value2\",\n\t\t\t\t})\n\t\t\t);\n\t\t\treturn [];\n\t\t},\n\t\tsaveMessages: async ({ nodeishFs, settings }) => {\n\t\t\tconst pathPattern = settings[\"plugin.mock-plugin\"]?.pathPattern.replace(\n\t\t\t\t\"{locale}\",\n\t\t\t\t\"en\"\n\t\t\t) as string;\n\t\t\tconst file = new TextEncoder().encode(\n\t\t\t\tJSON.stringify({\n\t\t\t\t\tkey1: \"value1\",\n\t\t\t\t\tkey2: \"value2\",\n\t\t\t\t\tkey3: \"value3\",\n\t\t\t\t})\n\t\t\t);\n\t\t\tawait nodeishFs.writeFile(pathPattern, file.buffer as ArrayBuffer);\n\t\t},\n\t\ttoBeImportedFiles: async ({ settings }) => {\n\t\t\tconst pathPattern = settings[\"plugin.mock-plugin\"]?.pathPattern.replace(\n\t\t\t\t\"{locale}\",\n\t\t\t\t\"en\"\n\t\t\t) as string;\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\tpath: pathPattern,\n\t\t\t\t\tlocale: \"en\",\n\t\t\t\t},\n\t\t\t];\n\t\t},\n\t};\n\n\tconst fs = Volume.fromJSON(mockRepo);\n\n\tconst loadMessagesSpy = vi.spyOn(mockPlugin, \"loadMessages\");\n\tconst saveMessagesSpy = vi.spyOn(mockPlugin, \"saveMessages\");\n\tconst toBeImportedFilesSpy = vi.spyOn(mockPlugin, \"toBeImportedFiles\");\n\tconst fsReadFileSpy = vi.spyOn(fs.promises, \"readFile\");\n\tconst fsWriteFileSpy = vi.spyOn(fs.promises, \"writeFile\");\n\n\tconst project = await loadProjectFromDirectory({\n\t\tfs: fs as any,\n\t\tpath: \"/project.inlang\",\n\t\tprovidePlugins: [mockPlugin],\n\t});\n\n\texpect(loadMessagesSpy).toHaveBeenCalled();\n\texpect(fsReadFileSpy).toHaveBeenCalledWith(\"/messages/en.json\", undefined);\n\n\t// todo test that saveMessages works too.\n\t// await project.db.insertInto(\"bundle\").defaultValues().execute();\n\n\t// const translationFile = await fs.readFile(\"/messages/en.json\", \"utf-8\");\n\n\t// expect(translationFile).toBe(\n\t// \tJSON.stringify({\n\t// \t\tkey1: \"value1\",\n\t// \t\tkey2: \"value2\",\n\t// \t\tkey3: \"value3\",\n\t// \t})\n\t// );\n\n\t// expect(fsWriteFileSpy).toHaveBeenCalledWith(\n\t// \t\"/messages/en.json\",\n\t// \tJSON.stringify({\n\t// \t\tkey1: \"value1\",\n\t// \t\tkey2: \"value2\",\n\t// \t\tkey3: \"value3\",\n\t// \t}),\n\t// \t\"utf-8\"\n\t// );\n\n\t// expect(saveMessagesSpy).toHaveBeenCalled();\n\t// expect(toBeImportedFilesSpy).toHaveBeenCalled();\n});\n\ntest(\"it can import plugins via http\", async () => {\n\tconst mockRepo = {\n\t\t\"/project.inlang/settings.json\": JSON.stringify({\n\t\t\tbaseLocale: \"en\",\n\t\t\tlocales: [\"en\"],\n\t\t\tmodules: [\"https://example.com/plugin.js\"],\n\t\t} satisfies ProjectSettings),\n\t};\n\n\tconst fs = Volume.fromJSON(mockRepo);\n\n\tconst mockPluginModule = `export default {\n\t\t\tkey: \"mock-plugin\"\t\n\t\t}`;\n\n\tglobal.fetch = vi.fn(() => Promise.resolve(new Response(mockPluginModule)));\n\n\tconst project = await loadProjectFromDirectory({\n\t\tfs: fs as any,\n\t\tpath: \"/project.inlang\",\n\t});\n\n\tconst plugins = await project.plugins.get();\n\n\texpect(global.fetch).toHaveBeenCalledWith(\"https://example.com/plugin.js\");\n\texpect(plugins.length).toBe(1);\n\n\tconst pluginCache = await project.lix.db\n\t\t.selectFrom(\"file\")\n\t\t.selectAll()\n\t\t.where(\"path\", \"like\", \"/cache/plugins/%\")\n\t\t.execute();\n\n\texpect(\n\t\tpluginCache.some(\n\t\t\t(file) => new TextDecoder().decode(file.data) === mockPluginModule\n\t\t),\n\t\t\"expecting the plugin to be cached\"\n\t).toBe(true);\n});\n\ntest(\"plugins that provide both loadMessages and importFiles should be allowed and the importFiles should be called\", async () => {\n\tconst mockRepo = {\n\t\t\"/project.inlang/settings.json\": JSON.stringify({\n\t\t\tbaseLocale: \"en\",\n\t\t\tlocales: [\"en\"],\n\t\t\tmodules: [],\n\t\t} satisfies ProjectSettings),\n\t};\n\n\tconst fs = Volume.fromJSON(mockRepo);\n\n\tconst mockPlugin: InlangPlugin = {\n\t\tkey: \"mock-plugin\",\n\t\tloadMessages: vi.fn(async () => []),\n\t\timportFiles: vi.fn(async () => {\n\t\t\treturn { bundles: [], messages: [], variants: [] };\n\t\t}),\n\t};\n\n\tconst project = await loadProjectFromDirectory({\n\t\tfs: fs as any,\n\t\tpath: \"/project.inlang\",\n\t\tprovidePlugins: [mockPlugin],\n\t});\n\n\texpect(mockPlugin.importFiles).toHaveBeenCalled();\n\texpect(mockPlugin.loadMessages).not.toHaveBeenCalled();\n});\n\ntest(\"providing multiple plugins that have legacy loadMessages and saveMessages function should be possible if they have import/export functions\", async () => {\n\tconst mockRepo = {\n\t\t\"/project.inlang/settings.json\": JSON.stringify({\n\t\t\tbaseLocale: \"en\",\n\t\t\tlocales: [\"en\"],\n\t\t\tmodules: [],\n\t\t} satisfies ProjectSettings),\n\t};\n\n\tconst fs = Volume.fromJSON(mockRepo);\n\n\tconst mockPlugin1: InlangPlugin = {\n\t\tkey: \"mock-plugin1\",\n\t\tloadMessages: vi.fn(async () => []),\n\t\timportFiles: vi.fn(async () => {\n\t\t\treturn { bundles: [], messages: [], variants: [] };\n\t\t}),\n\t};\n\n\tconst mockPlugin2: InlangPlugin = {\n\t\tkey: \"mock-plugin2\",\n\t\tloadMessages: vi.fn(async () => []),\n\t\timportFiles: vi.fn(async () => {\n\t\t\treturn { bundles: [], messages: [], variants: [] };\n\t\t}),\n\t};\n\n\tconst project = await loadProjectFromDirectory({\n\t\tfs: fs as any,\n\t\tpath: \"/project.inlang\",\n\t\tprovidePlugins: [mockPlugin1, mockPlugin2],\n\t});\n\n\texpect(mockPlugin1.importFiles).toHaveBeenCalled();\n\texpect(mockPlugin1.loadMessages).not.toHaveBeenCalled();\n\n\texpect(mockPlugin2.importFiles).toHaveBeenCalled();\n\texpect(mockPlugin2.loadMessages).not.toHaveBeenCalled();\n});\n"],"names":[],"mappings":"AAAA,sDAAsD;;;AAEtD,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAChE,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAC7D,OAAO,EAAE,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AACxC,OAAO,EACN,wBAAwB,EACxB,uBAAuB,EACvB,yBAAyB,GACzB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,kBAAkB,EAAE,MAAM,0CAA0C,CAAC;AAC9E,OAAO,EAAE,IAAI,EAAE,MAAM,2BAA2B,CAAC;AAMjD,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AACrE,OAAO,EAAE,kBAAkB,EAAE,MAAM,0CAA0C,CAAC;AAE9E,IAAI,CAAC,gGAAgG,EAAE,KAAK,IAAI,EAAE;IACjH,MAAM,gBAAgB,GAAiB;QACtC,GAAG,EAAE,oBAAoB;QACzB,YAAY,EAAE,KAAK,IAAI,EAAE;YACxB,OAAO,EAAE,CAAC;QACX,CAAC;QACD,YAAY,EAAE,KAAK,IAAI,EAAE,GAAE,CAAC;KAC5B,CAAC;IAEF,MAAM,iBAAiB,GAAiB;QACvC,GAAG,EAAE,sBAAsB;QAC3B,YAAY,EAAE,KAAK,IAAI,EAAE;YACxB,OAAO,EAAE,CAAC;QACX,CAAC;QACD,YAAY,EAAE,KAAK,IAAI,EAAE,GAAE,CAAC;KAC5B,CAAC;IAEF,MAAM,sBAAsB,GAAiB;QAC5C,GAAG,EAAE,2BAA2B;QAChC,WAAW,EAAE,GAAG,EAAE;YACjB,OAAO,EAAE,CAAC;QACX,CAAC;QACD,WAAW,EAAE,GAAG,EAAE;YACjB,OAAO,EAAS,CAAC;QAClB,CAAC;KACD,CAAC;IAEF,MAAM,MAAM,CACX,CAAC,KAAK,IAAI,EAAE;QACX,MAAM,wBAAwB,CAAC;YAC9B,EAAE,EAAE,MAAM,CAAC,QAAQ,CAAC;gBACnB,gCAAgC,EAAE,IAAI,CAAC,SAAS,CAAC;oBAChD,UAAU,EAAE,IAAI;oBAChB,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC;oBACrB,OAAO,EAAE,EAAE;iBACe,CAAC;aAC5B,CAAQ;YACT,IAAI,EAAE,kBAAkB;YACxB,cAAc,EAAE;gBACf,gBAAgB;gBAChB,iBAAiB;gBACjB,sBAAsB;aACtB;SACD,CAAC,CAAC;IACJ,CAAC,CAAC,EAAE,CACJ,CAAC,OAAO,CAAC,YAAY,EAAE,CAAC;IAEzB,MAAM,MAAM,CACX,CAAC,KAAK,IAAI,EAAE;QACX,MAAM,wBAAwB,CAAC;YAC9B,EAAE,EAAE,MAAM,CAAC,QAAQ,CAAC;gBACnB,gCAAgC,EAAE,IAAI,CAAC,SAAS,CAAC;oBAChD,UAAU,EAAE,IAAI;oBAChB,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC;oBACrB,OAAO,EAAE,EAAE;iBACe,CAAC;aAC5B,CAAQ;YACT,IAAI,EAAE,kBAAkB;YACxB,cAAc,EAAE;gBACf,gBAAgB;gBAChB,iBAAiB;gBACjB,sBAAsB;aACtB;SACD,CAAC,CAAC;IACJ,CAAC,CAAC,EAAE,CACJ,CAAC,OAAO,CAAC,YAAY,EAAE,CAAC;AAC1B,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,6EAA6E,EAAE,KAAK,IAAI,EAAE;IAC9F,MAAM,gBAAgB,GAAiB;QACtC,EAAE,EAAE,oBAAoB;QACxB,4DAA4D;QAC5D,GAAG,EAAE,SAAS;QACd,YAAY,EAAE,KAAK,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,EAAE;YAC/C,MAAM,WAAW,GAAG,QAAQ,CAAC,oBAAoB,CAAC,EAAE,WAAqB,CAAC;YAE1E,MAAM,QAAQ,GAAgB,EAAE,CAAC;YAEjC,gEAAgE;YAChE,KAAK,MAAM,WAAW,IAAI,QAAQ,CAAC,YAAY,EAAE,CAAC;gBACjD,MAAM,IAAI,GAAG,MAAM,SAAS,CAAC,QAAQ,CACpC,WAAW,CAAC,OAAO,CAAC,eAAe,EAAE,WAAW,CAAC,CACjD,CAAC;gBAEF,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CACxC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAC3B,EAAE,CAAC;oBACH,MAAM,eAAe,GAAG,QAAQ,CAAC,IAAI,CACpC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,EAAE,KAAK,GAAG,CAC/B,CAAC;oBACF,MAAM,OAAO,GAAG;wBACf,WAAW,EAAE,WAAW;wBACxB,KAAK,EAAE,EAAE;wBACT,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;qBAC5B,CAAC;oBACf,IAAI,eAAe,KAAK,SAAS,EAAE,CAAC;wBACnC,eAAe,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;oBACxC,CAAC;yBAAM,CAAC;wBACP,QAAQ,CAAC,IAAI,CAAC;4BACb,KAAK,EAAE,EAAE;4BACT,EAAE,EAAE,GAAG;4BACP,SAAS,EAAE,EAAE;4BACb,QAAQ,EAAE,CAAC,OAAO,CAAC;yBACnB,CAAC,CAAC;oBACJ,CAAC;gBACF,CAAC;YACF,CAAC;YAED,OAAO,QAAQ,CAAC;QACjB,CAAC;QACD,YAAY,EAAE,KAAK,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,EAAE;YACzD,MAAM,WAAW,GAAG,QAAQ,CAAC,oBAAoB,CAAC,EAAE,WAAqB,CAAC;YAC1E,KAAK,MAAM,WAAW,IAAI,QAAQ,CAAC,YAAa,EAAE,CAAC;gBAClD,MAAM,kBAAkB,GAAG,EAA4B,CAAC;gBACxD,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;oBAChC,MAAM,kBAAkB,GAAG,OAAO,CAAC,QAAQ,CAAC,MAAM,CACjD,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,WAAW,KAAK,WAAW,CAChD,CAAC;oBACF,IAAI,kBAAkB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;wBACnC,6CAA6C;oBAC9C,CAAC;yBAAM,IAAI,kBAAkB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;wBAC5C,IACC,kBAAkB,CAAC,CAAC,CAAE,CAAC,OAAO,CAAC,MAAM,IAAI,CAAC;4BAC1C,kBAAkB,CAAC,CAAC,CAAE,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,IAAI,KAAK,MAAM,EACjD,CAAC;4BACF,SAAS;wBACV,CAAC;wBACD,kBAAkB,CAAC,OAAO,CAAC,EAAE,CAAC,GAC7B,kBAAkB,CAAC,CAAC,CAAE,CAAC,OAAO,CAAC,CAAC,CAChC,CAAC,KAAK,CAAC;oBACT,CAAC;oBACD,aAAa;gBACd,CAAC;gBACD,MAAM,SAAS,CAAC,SAAS,CACxB,WAAW,CAAC,OAAO,CAAC,eAAe,EAAE,WAAW,CAAC,EACjD,IAAI,CAAC,SAAS,CAAC,kBAAkB,EAAE,IAAI,EAAE,CAAC,CAAC,CAC3C,CAAC;YACH,CAAC;QACF,CAAC;KACD,CAAC;IACF,MAAM,QAAQ,GAAG;QAChB,aAAa,EAAE,eAAe;QAC9B,gBAAgB,EAAE,4BAA4B;QAC9C,4BAA4B,EAAE,IAAI,CAAC,SAAS,CAAC;YAC5C,IAAI,EAAE,QAAQ;YACd,IAAI,EAAE,QAAQ;SACd,CAAC;QACF,4BAA4B,EAAE,IAAI,CAAC,SAAS,CAAC;YAC5C,IAAI,EAAE,OAAO;YACb,IAAI,EAAE,OAAO;SACb,CAAC;QACF,gCAAgC,EAAE,IAAI,CAAC,SAAS,CAAC;YAChD,UAAU,EAAE,IAAI;YAChB,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC;YACrB,OAAO,EAAE,CAAC,kBAAkB,CAAC;YAC7B,oBAAoB,EAAE;gBACrB,WAAW,EAAE,uCAAuC;aACpD;SACyB,CAAC;KAC5B,CAAC;IAEF,MAAM,EAAE,GAAG,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAErC,IAAI,OAAO,GAAG,MAAM,wBAAwB,CAAC;QAC5C,EAAE,EAAE,EAAS;QACb,IAAI,EAAE,kBAAkB;QACxB,cAAc,EAAE,CAAC,gBAAgB,CAAC;KAClC,CAAC,CAAC;IAEH,MAAM,kBAAkB,CAAC,OAAO,CAAC,EAAE,EAAE;QACpC,EAAE,EAAE,QAAQ;QACZ,QAAQ,EAAE;YACT;gBACC,EAAE,EAAE,cAAc;gBAClB,QAAQ,EAAE,aAAa;gBACvB,MAAM,EAAE,IAAI;gBACZ,SAAS,EAAE,EAAE;gBACb,QAAQ,EAAE;oBACT;wBACC,SAAS,EAAE,cAAc;wBACzB,OAAO,EAAE;4BACR;gCACC,IAAI,EAAE,MAAM;gCACZ,KAAK,EAAE,MAAM;6BACb;yBACD;qBACD;iBACD;aACD;SACD;KACD,CAAC,CAAC;IAEH,MAAM,sBAAsB,CAAC;QAC5B,EAAE,EAAE,EAAE,CAAC,QAAe;QACtB,IAAI,EAAE,kBAAkB;QACxB,OAAO;KACP,CAAC,CAAC;IAEH,OAAO,GAAG,MAAM,wBAAwB,CAAC;QACxC,EAAE,EAAE,EAAS;QACb,IAAI,EAAE,kBAAkB;QACxB,cAAc,EAAE,CAAC,gBAAgB,CAAC;KAClC,CAAC,CAAC;IAEH,MAAM,OAAO,GAAG,MAAM,kBAAkB,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC;IAE/D,MAAM,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAExE,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC/B,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1D,MAAM,CACJ,cAAc,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,CAAU,EAAE,KAAK,CACxE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAEf,WAAW;IACX,6DAA6D;IAC7D,UAAU;IACV,4EAA4E;IAC5E,mBAAmB;IAEnB,6DAA6D;IAC7D,UAAU;IACV,4EAA4E;IAC5E,oBAAoB;IAEpB,6DAA6D;IAC7D,UAAU;IACV,4EAA4E;IAC5E,mBAAmB;AACpB,CAAC,CAAC,CAAC;AAEH,MAAM,YAAY,GAAG;IACpB,UAAU,EAAE,IAAI;IAChB,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC;IACrB,OAAO,EAAE,EAAE;CACe,CAAC;AAE5B,MAAM,aAAa,GAAG;IACrB,sCAAsC,EAAE,aAAa;IACrD,4BAA4B,EAAE,WAAW;IACzC,iCAAiC,EAAE,gBAAgB;IACnD,2BAA2B,EAAE,cAAc;IAC3C,+BAA+B,EAAE,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC;CAC7D,CAAC;AAEF,QAAQ,CAAC,mEAAmE,EAAE,KAAK,IAAI,EAAE;IACxF,IAAI,CAAC,+FAA+F,EAAE,KAAK,IAAI,EAAE;QAChH,MAAM,YAAY,GAAG,GAAG,CAAC;QACzB,MAAM,EAAE,GAAG,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC;QAE1C,MAAM,OAAO,GAAG,MAAM,wBAAwB,CAAC;YAC9C,EAAE,EAAE,EAAS;YACb,IAAI,EAAE,iBAAiB;YACvB,YAAY,EAAE,YAAY;SAC1B,CAAC,CAAC;QAEH,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,SAAS,EAAE,CAAC,OAAO,EAAE,CAAC;QAE5E,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,CACxB,CAAC,GAAG,CAAC,CAAC,wBAAwB,GAAG,CAAC,CAAC,gBAAgB,CACnD,CAAC;QAEF,MAAM,WAAW,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE;YAC9C,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACrD,OAAO,GAAG,CAAC;QACZ,CAAC,EAAE,EAAS,CAAC,CAAC;QAEd,MAAM,CAAC,WAAW,CAAC,uBAAuB,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QACjE,MAAM,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QACrD,MAAM,CAAC,WAAW,CAAC,kBAAkB,CAAC,CAAC,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;QAC/D,MAAM,CAAC,WAAW,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QACvD,MAAM,CAAC,WAAW,CAAC,gBAAgB,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC,CAAC;IAC1E,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,iDAAiD,EAAE,KAAK,IAAI,EAAE;QAClE,MAAM,YAAY,GAAG,GAAG,CAAC;QACzB,MAAM,EAAE,GAAG,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC;QAE1C,MAAM,OAAO,GAAG,MAAM,wBAAwB,CAAC;YAC9C,EAAE,EAAE,EAAS;YACb,IAAI,EAAE,iBAAiB;YACvB,YAAY,EAAE,YAAY;SAC1B,CAAC,CAAC;QAEH,EAAE,CAAC,aAAa,CACf,wCAAwC,EACxC,qBAAqB,EACrB;YACC,QAAQ,EAAE,OAAO;SACjB,CACD,CAAC;QAEF,yDAAyD;QACzD,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,YAAY,GAAG,EAAE,CAAC,CAAC,CAAC;QAEvE,MAAM,eAAe,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,EAAE;aAC1C,UAAU,CAAC,MAAM,CAAC;aAClB,SAAS,EAAE;aACX,KAAK,CAAC,MAAM,EAAE,GAAG,EAAE,yBAAyB,CAAC;aAC7C,uBAAuB,EAAE,CAAC;QAE5B,MAAM,CAAC,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAC1D,qBAAqB,CACrB,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,iDAAiD,EAAE,KAAK,IAAI,EAAE;QAClE,MAAM,YAAY,GAAG,GAAG,CAAC;QACzB,MAAM,EAAE,GAAG,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC;QAE1C,MAAM,OAAO,GAAG,MAAM,wBAAwB,CAAC;YAC9C,EAAE,EAAE,EAAS;YACb,IAAI,EAAE,iBAAiB;YACvB,YAAY,EAAE,YAAY;SAC1B,CAAC,CAAC;QAEH,mDAAmD;QACnD,EAAE,CAAC,aAAa,CACf,+BAA+B,EAC/B,IAAI,CAAC,SAAS,CAAC;YACd,GAAG,YAAY;YACf,UAAU,EAAE,qCAAqC;SACjD,CAAC,CACF,CAAC;QAEF,qCAAqC;QACrC,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,YAAY,GAAG,EAAE,CAAC,CAAC,CAAC;QACvE,MAAM,SAAS,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,EAAE;aACpC,UAAU,CAAC,MAAM,CAAC;aAClB,SAAS,EAAE;aACX,KAAK,CAAC,MAAM,EAAE,GAAG,EAAE,gBAAgB,CAAC;aACpC,uBAAuB,EAAE,CAAC;QAE5B,MAAM,yBAAyB,GAAG,IAAI,CAAC,KAAK,CAC3C,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,CACxC,CAAC;QAEF,MAAM,CAAC,yBAAyB,CAAC,UAAU,CAAC,CAAC,IAAI,CAChD,qCAAqC,CACrC,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,+CAA+C,EAAE,KAAK,IAAI,EAAE;QAChE,MAAM,YAAY,GAAG,GAAG,CAAC;QACzB,MAAM,EAAE,GAAG,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC;QAE1C,MAAM,OAAO,GAAG,MAAM,wBAAwB,CAAC;YAC9C,EAAE,EAAE,EAAS;YACb,IAAI,EAAE,iBAAiB;YACvB,YAAY,EAAE,YAAY;SAC1B,CAAC,CAAC;QAEH,MAAM,gBAAgB,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,EAAE;aAC3C,UAAU,CAAC,MAAM,CAAC;aAClB,SAAS,EAAE;aACX,KAAK,CAAC,MAAM,EAAE,GAAG,EAAE,YAAY,CAAC;aAChC,OAAO,EAAE,CAAC;QAEZ,MAAM,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAExC,mDAAmD;QACnD,EAAE,CAAC,UAAU,CAAC,2BAA2B,CAAC,CAAC;QAE3C,qCAAqC;QACrC,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,YAAY,GAAG,EAAE,CAAC,CAAC,CAAC;QACvE,MAAM,cAAc,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,EAAE;aACzC,UAAU,CAAC,MAAM,CAAC;aAClB,SAAS,EAAE;aACX,KAAK,CAAC,MAAM,EAAE,GAAG,EAAE,YAAY,CAAC;aAChC,OAAO,EAAE,CAAC;QAEZ,MAAM,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACvC,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,iDAAiD,EAAE,KAAK,IAAI,EAAE;QAClE,MAAM,YAAY,GAAG,GAAG,CAAC;QACzB,MAAM,EAAE,GAAG,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC;QAE1C,MAAM,OAAO,GAAG,MAAM,wBAAwB,CAAC;YAC9C,EAAE,EAAE,EAAS;YACb,IAAI,EAAE,iBAAiB;YACvB,YAAY,EAAE,YAAY;SAC1B,CAAC,CAAC;QAEH,MAAM,OAAO,CAAC,GAAG,CAAC,EAAE;aAClB,UAAU,CAAC,MAAM,CAAC;aAClB,MAAM,CAAC;YACP,IAAI,EAAE,0BAA0B;YAChC,IAAI,EAAE,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,kBAAkB,CAAC;SAClD,CAAC;aACD,OAAO,EAAE,CAAC;QAEZ,yDAAyD;QACzD,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,YAAY,GAAG,EAAE,CAAC,CAAC,CAAC;QAEvE,MAAM,uBAAuB,GAAG,EAAE;aAChC,YAAY,CAAC,yCAAyC,CAAC;aACvD,QAAQ,EAAE,CAAC;QACb,MAAM,CAAC,uBAAuB,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;IAC1D,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,iDAAiD,EAAE,KAAK,IAAI,EAAE;QAClE,MAAM,YAAY,GAAG,GAAG,CAAC;QACzB,MAAM,EAAE,GAAG,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC;QAE1C,MAAM,OAAO,GAAG,MAAM,wBAAwB,CAAC;YAC9C,EAAE,EAAE,EAAS;YACb,IAAI,EAAE,iBAAiB;YACvB,YAAY,EAAE,YAAY;SAC1B,CAAC,CAAC;QAEH,sCAAsC;QACtC,mEAAmE;QACnE,MAAM,OAAO,CAAC,GAAG,CAAC,EAAE;aAClB,WAAW,CAAC,MAAM,CAAC;aACnB,KAAK,CAAC,MAAM,EAAE,GAAG,EAAE,gBAAgB,CAAC;aACpC,GAAG,CAAC;YACJ,IAAI,EAAE,IAAI,WAAW,EAAE,CAAC,MAAM,CAC7B,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,YAAY,EAAE,UAAU,EAAE,mBAAmB,EAAE,CAAC,CACpE;SACD,CAAC;aACD,OAAO,EAAE,CAAC;QAEZ,yDAAyD;QACzD,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,YAAY,GAAG,EAAE,CAAC,CAAC,CAAC;QAEvE,MAAM,UAAU,GAAG,EAAE,CAAC,YAAY,CAAC,+BAA+B,CAAC,CAAC;QACpE,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,QAAQ,EAAE,CAAC,CAAC;QAEnD,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;IACvD,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,mDAAmD,EAAE,KAAK,IAAI,EAAE;QACpE,MAAM,YAAY,GAAG,GAAG,CAAC;QACzB,MAAM,EAAE,GAAG,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC;QAE1C,MAAM,OAAO,GAAG,MAAM,wBAAwB,CAAC;YAC9C,EAAE,EAAE,EAAS;YACb,IAAI,EAAE,iBAAiB;YACvB,YAAY,EAAE,YAAY;SAC1B,CAAC,CAAC;QAEH,sCAAsC;QACtC,mEAAmE;QACnE,MAAM,OAAO,CAAC,GAAG,CAAC,EAAE;aAClB,UAAU,CAAC,MAAM,CAAC;aAClB,KAAK,CAAC,MAAM,EAAE,GAAG,EAAE,aAAa,CAAC;aACjC,OAAO,EAAE,CAAC;QAEZ,yDAAyD;QACzD,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,YAAY,GAAG,EAAE,CAAC,CAAC,CAAC;QAEvE,MAAM,gBAAgB,GAAG,EAAE,CAAC,UAAU,CAAC,4BAA4B,CAAC,CAAC;QAErE,MAAM,CAAC,gBAAgB,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACtC,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,wEAAwE,EAAE,KAAK,IAAI,EAAE;QACzF,MAAM,YAAY,GAAG,GAAG,CAAC;QACzB,MAAM,EAAE,GAAG,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC;QAE1C,MAAM,OAAO,GAAG,MAAM,wBAAwB,CAAC;YAC9C,EAAE,EAAE,EAAS;YACb,IAAI,EAAE,iBAAiB;YACvB,YAAY,EAAE,YAAY;SAC1B,CAAC,CAAC;QAEH,iDAAiD;QACjD,mFAAmF;QACnF,EAAE,CAAC,aAAa,CACf,+BAA+B,EAC/B,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,YAAY,EAAE,UAAU,EAAE,YAAY,EAAE,CAAC,CAC7D,CAAC;QAEF,kDAAkD;QAClD,MAAM,OAAO,CAAC,GAAG,CAAC,EAAE;aAClB,WAAW,CAAC,MAAM,CAAC;aACnB,KAAK,CAAC,MAAM,EAAE,GAAG,EAAE,gBAAgB,CAAC;aACpC,GAAG,CAAC;YACJ,IAAI,EAAE,IAAI,WAAW,EAAE,CAAC,MAAM,CAC7B,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,CAAC,CAC9D;SACD,CAAC;aACD,OAAO,EAAE,CAAC;QAEZ,yDAAyD;QACzD,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC;QAE1D,MAAM,iBAAiB,GAAG,EAAE,CAAC,YAAY,CAAC,+BAA+B,CAAC,CAAC;QAC3E,MAAM,eAAe,GAAG,IAAI,CAAC,KAAK,CAAC,iBAAiB,CAAC,QAAQ,EAAE,CAAC,CAAC;QAEjE,MAAM,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAEtD,MAAM,gBAAgB,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,EAAE;aAC3C,UAAU,CAAC,MAAM,CAAC;aAClB,SAAS,EAAE;aACX,KAAK,CAAC,MAAM,EAAE,GAAG,EAAE,gBAAgB,CAAC;aACpC,uBAAuB,EAAE,CAAC;QAE5B,MAAM,+BAA+B,GAAG,IAAI,CAAC,KAAK,CACjD,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAC/C,CAAC;QAEF,MAAM,CAAC,+BAA+B,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IACvE,CAAC,CAAC,CAAC;AACJ,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,yDAAyD,EAAE,KAAK,IAAI,EAAE;IAC1E,MAAM,IAAI,GAAG;QACZ,+BAA+B,EAAE,IAAI,CAAC,SAAS,CAAC;YAC/C,UAAU,EAAE,IAAI;YAChB,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC;YACrB,OAAO,EAAE,EAAE;SACe,CAAC;KAC5B,CAAC;IAEF,MAAM,EAAE,GAAG,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IAEjC,MAAM,SAAS,GAAG,IAAI,KAAK,CAAC,EAAE,EAAE;QAC/B,GAAG,EAAE,CAAC,MAAM,EAAE,IAAI,EAAE,EAAE;YACrB,IAAI,IAAI,KAAK,UAAU,EAAE,CAAC;gBACzB,kCAAkC;gBAClC,OAAO,IAAI,KAAK,CAAC,MAAM,CAAC,QAAQ,EAAE;oBACjC,GAAG,EAAE,CAAC,cAAc,EAAE,YAAY,EAAE,EAAE;wBACrC,IAAI,YAAY,KAAK,UAAU,EAAE,CAAC;4BACjC,2CAA2C;4BAC3C,OAAO,CAAC,IAAI,EAAE,GAAG,IAAI,EAAE,EAAE;gCACxB,IAAI,IAAI,CAAC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,CAAC;oCACrC,MAAM,IAAI,KAAK,CAAC,YAAY,CAAC,CAAC;gCAC/B,CAAC;gCACD,OAAO,cAAc,CAAC,QAAQ,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,CAAC;4BAC/C,CAAC,CAAC;wBACH,CAAC;wBACD,OAAO,OAAO,CAAC,GAAG,CAAC,cAAc,EAAE,YAAY,CAAC,CAAC;oBAClD,CAAC;iBACD,CAAC,CAAC;YACJ,CAAC;YACD,OAAO,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QAClC,CAAC;KACD,CAAC,CAAC;IAEH,MAAM,UAAU,GAAiB;QAChC,GAAG,EAAE,aAAa;QAClB,WAAW,EAAE,KAAK,IAAI,EAAE;YACvB,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;QACpD,CAAC;QACD,iBAAiB,EAAE,KAAK,IAAI,EAAE;YAC7B,OAAO,CAAC,EAAE,IAAI,EAAE,kBAAkB,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;QACvD,CAAC;KACD,CAAC;IAEF,MAAM,OAAO,GAAG,MAAM,wBAAwB,CAAC;QAC9C,EAAE,EAAE,SAAgB;QACpB,IAAI,EAAE,iBAAiB;QACvB,cAAc,EAAE,CAAC,UAAU,CAAC;KAC5B,CAAC,CAAC;IAEH,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC;IAC1C,iGAAiG;IACjG,MAAM,CAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAC/B,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,uBAAuB,CAAC,CAAC;AAC3D,CAAC,CAAC,CAAC;AAEH,oEAAoE;AACpE,IAAI,CAAC,6EAA6E,EAAE,KAAK,IAAI,EAAE;IAC9F,MAAM,IAAI,GAAG;QACZ,+BAA+B,EAAE,IAAI,CAAC,SAAS,CAAC;YAC/C,UAAU,EAAE,IAAI;YAChB,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC;YACrB,OAAO,EAAE,EAAE;SACe,CAAC;KAC5B,CAAC;IAEF,MAAM,EAAE,GAAG,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IAEjC,MAAM,UAAU,GAAiB;QAChC,GAAG,EAAE,aAAa;QAClB,WAAW,EAAE,KAAK,IAAI,EAAE;YACvB,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;QACpD,CAAC;QACD,iBAAiB,EAAE,KAAK,IAAI,EAAE;YAC7B,OAAO,CAAC,EAAE,IAAI,EAAE,+BAA+B,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;QACpE,CAAC;KACD,CAAC;IAEF,MAAM,OAAO,GAAG,MAAM,wBAAwB,CAAC;QAC9C,EAAE,EAAE,EAAS;QACb,IAAI,EAAE,iBAAiB;QACvB,cAAc,EAAE,CAAC,UAAU,CAAC;KAC5B,CAAC,CAAC;IAEH,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC;IAC1C,MAAM,CAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;AAChC,CAAC,CAAC,CAAC;AAEH,oEAAoE;AACpE,IAAI,CAAC,+CAA+C,EAAE,KAAK,IAAI,EAAE;IAChE,MAAM,IAAI,GAAG;QACZ,cAAc,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;QAClC,+BAA+B,EAAE,IAAI,CAAC,SAAS,CAAC;YAC/C,UAAU,EAAE,IAAI;YAChB,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC;SACK,CAAC;KAC5B,CAAC;IAEF,MAAM,EAAE,GAAG,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IAEjC,MAAM,UAAU,GAAiB;QAChC,GAAG,EAAE,aAAa;QAClB,iBAAiB,EAAE,KAAK,IAAI,EAAE;YAC7B,OAAO;gBACN;oBACC,IAAI,EAAE,cAAc;oBACpB,MAAM,EAAE,MAAM;oBACd,QAAQ,EAAE;wBACT,GAAG,EAAE,KAAK;qBACV;iBACD;aACD,CAAC;QACH,CAAC;QACD,WAAW,EAAE,KAAK,IAAI,EAAE;YACvB,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;QACpD,CAAC;KACD,CAAC;IAEF,MAAM,OAAO,GAAG,EAAE,CAAC,KAAK,CAAC,UAAU,EAAE,mBAAmB,CAAC,CAAC;IAC1D,MAAM,SAAS,GAAG,EAAE,CAAC,KAAK,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;IAEtD,MAAM,OAAO,GAAG,MAAM,wBAAwB,CAAC;QAC9C,EAAE,EAAE,EAAS;QACb,IAAI,EAAE,iBAAiB;QACvB,cAAc,EAAE,CAAC,UAAU,CAAC;KAC5B,CAAC,CAAC;IAEH,MAAM,CAAC,OAAO,CAAC,CAAC,gBAAgB,EAAE,CAAC;IAEnC,MAAM,CAAC,SAAS,CAAC,CAAC,oBAAoB,CACrC,MAAM,CAAC,gBAAgB,CAAC;QACvB,KAAK,EAAE;YACN,MAAM,CAAC,gBAAgB,CAAC;gBACvB,yBAAyB,EAAE;oBAC1B,GAAG,EAAE,KAAK;iBACV;aACD,CAAC;SACF;KACD,CAAC,CACF,CAAC;AACH,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,8GAA8G,EAAE,KAAK,IAAI,EAAE;IAC/H,MAAM,QAAQ,GAAG;QAChB,+BAA+B,EAAE,uCAAuC;QACxE,6BAA6B,EAC5B,8CAA8C;QAC/C,uCAAuC,EAAE,IAAI,CAAC,SAAS,CAAC;YACvD,UAAU,EAAE,IAAI;YAChB,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC;YACrB,OAAO,EAAE;gBACR,iCAAiC;gBACjC,+BAA+B;aAC/B;SACyB,CAAC;KAC5B,CAAC;IAEF,MAAM,EAAE,GAAG,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAErC,MAAM,OAAO,GAAG,MAAM,wBAAwB,CAAC;QAC9C,EAAE,EAAE,EAAS;QACb,IAAI,EAAE,yBAAyB;KAC/B,CAAC,CAAC;IAEH,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC;IAC5C,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC;IAC1C,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC;IAE9C,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC/B,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IAE5C,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC9B,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,yBAAyB,CAAC,CAAC;IAE5D,oDAAoD;IACpD,iCAAiC;IACjC,MAAM,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,iCAAiC,CAAC,CAAC;AACvE,CAAC,CAAC,CAAC;AAEH,iDAAiD;AACjD,IAAI,CAAC,wEAAwE,EAAE,KAAK,IAAI,EAAE;IACzF,OAAO,CAAC,GAAG,GAAG,GAAG,EAAE,CAAC,GAAG,CAAC;IAExB,MAAM,QAAQ,GAAG;QAChB,mBAAmB,EAAE,IAAI,CAAC,SAAS,CAAC;YACnC,IAAI,EAAE,QAAQ;YACd,IAAI,EAAE,QAAQ;SACd,CAAC;QACF,+BAA+B,EAAE,IAAI,CAAC,SAAS,CAAC;YAC/C,UAAU,EAAE,IAAI;YAChB,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC;YACrB,oBAAoB,EAAE;gBACrB,WAAW,EAAE,0BAA0B;aACvC;SACyB,CAAC;KAC5B,CAAC;IAEF,MAAM,UAAU,GAAiB;QAChC,GAAG,EAAE,aAAa;QAClB,YAAY,EAAE,KAAK,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,EAAE;YAC/C,MAAM,WAAW,GAAG,QAAQ,CAAC,oBAAoB,CAAC,EAAE,WAAW,CAAC,OAAO,CACtE,UAAU,EACV,IAAI,CACM,CAAC;YACZ,MAAM,IAAI,GAAG,MAAM,SAAS,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;YACnD,uDAAuD;YACvD,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,IAAI,CAC3B,IAAI,CAAC,SAAS,CAAC;gBACd,IAAI,EAAE,QAAQ;gBACd,IAAI,EAAE,QAAQ;aACd,CAAC,CACF,CAAC;YACF,OAAO,EAAE,CAAC;QACX,CAAC;QACD,YAAY,EAAE,KAAK,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,EAAE;YAC/C,MAAM,WAAW,GAAG,QAAQ,CAAC,oBAAoB,CAAC,EAAE,WAAW,CAAC,OAAO,CACtE,UAAU,EACV,IAAI,CACM,CAAC;YACZ,MAAM,IAAI,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CACpC,IAAI,CAAC,SAAS,CAAC;gBACd,IAAI,EAAE,QAAQ;gBACd,IAAI,EAAE,QAAQ;gBACd,IAAI,EAAE,QAAQ;aACd,CAAC,CACF,CAAC;YACF,MAAM,SAAS,CAAC,SAAS,CAAC,WAAW,EAAE,IAAI,CAAC,MAAqB,CAAC,CAAC;QACpE,CAAC;QACD,iBAAiB,EAAE,KAAK,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE;YACzC,MAAM,WAAW,GAAG,QAAQ,CAAC,oBAAoB,CAAC,EAAE,WAAW,CAAC,OAAO,CACtE,UAAU,EACV,IAAI,CACM,CAAC;YACZ,OAAO;gBACN;oBACC,IAAI,EAAE,WAAW;oBACjB,MAAM,EAAE,IAAI;iBACZ;aACD,CAAC;QACH,CAAC;KACD,CAAC;IAEF,MAAM,EAAE,GAAG,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAErC,MAAM,eAAe,GAAG,EAAE,CAAC,KAAK,CAAC,UAAU,EAAE,cAAc,CAAC,CAAC;IAC7D,MAAM,eAAe,GAAG,EAAE,CAAC,KAAK,CAAC,UAAU,EAAE,cAAc,CAAC,CAAC;IAC7D,MAAM,oBAAoB,GAAG,EAAE,CAAC,KAAK,CAAC,UAAU,EAAE,mBAAmB,CAAC,CAAC;IACvE,MAAM,aAAa,GAAG,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;IACxD,MAAM,cAAc,GAAG,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC;IAE1D,MAAM,OAAO,GAAG,MAAM,wBAAwB,CAAC;QAC9C,EAAE,EAAE,EAAS;QACb,IAAI,EAAE,iBAAiB;QACvB,cAAc,EAAE,CAAC,UAAU,CAAC;KAC5B,CAAC,CAAC;IAEH,MAAM,CAAC,eAAe,CAAC,CAAC,gBAAgB,EAAE,CAAC;IAC3C,MAAM,CAAC,aAAa,CAAC,CAAC,oBAAoB,CAAC,mBAAmB,EAAE,SAAS,CAAC,CAAC;IAE3E,yCAAyC;IACzC,mEAAmE;IAEnE,2EAA2E;IAE3E,gCAAgC;IAChC,oBAAoB;IACpB,oBAAoB;IACpB,oBAAoB;IACpB,oBAAoB;IACpB,MAAM;IACN,KAAK;IAEL,+CAA+C;IAC/C,wBAAwB;IACxB,oBAAoB;IACpB,oBAAoB;IACpB,oBAAoB;IACpB,oBAAoB;IACpB,OAAO;IACP,WAAW;IACX,KAAK;IAEL,8CAA8C;IAC9C,mDAAmD;AACpD,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,gCAAgC,EAAE,KAAK,IAAI,EAAE;IACjD,MAAM,QAAQ,GAAG;QAChB,+BAA+B,EAAE,IAAI,CAAC,SAAS,CAAC;YAC/C,UAAU,EAAE,IAAI;YAChB,OAAO,EAAE,CAAC,IAAI,CAAC;YACf,OAAO,EAAE,CAAC,+BAA+B,CAAC;SAChB,CAAC;KAC5B,CAAC;IAEF,MAAM,EAAE,GAAG,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAErC,MAAM,gBAAgB,GAAG;;IAEtB,CAAC;IAEJ,MAAM,CAAC,KAAK,GAAG,EAAE,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,QAAQ,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC;IAE5E,MAAM,OAAO,GAAG,MAAM,wBAAwB,CAAC;QAC9C,EAAE,EAAE,EAAS;QACb,IAAI,EAAE,iBAAiB;KACvB,CAAC,CAAC;IAEH,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC;IAE5C,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,oBAAoB,CAAC,+BAA+B,CAAC,CAAC;IAC3E,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAE/B,MAAM,WAAW,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,EAAE;SACtC,UAAU,CAAC,MAAM,CAAC;SAClB,SAAS,EAAE;SACX,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,kBAAkB,CAAC;SACzC,OAAO,EAAE,CAAC;IAEZ,MAAM,CACL,WAAW,CAAC,IAAI,CACf,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,gBAAgB,CAClE,EACD,mCAAmC,CACnC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACd,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,+GAA+G,EAAE,KAAK,IAAI,EAAE;IAChI,MAAM,QAAQ,GAAG;QAChB,+BAA+B,EAAE,IAAI,CAAC,SAAS,CAAC;YAC/C,UAAU,EAAE,IAAI;YAChB,OAAO,EAAE,CAAC,IAAI,CAAC;YACf,OAAO,EAAE,EAAE;SACe,CAAC;KAC5B,CAAC;IAEF,MAAM,EAAE,GAAG,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAErC,MAAM,UAAU,GAAiB;QAChC,GAAG,EAAE,aAAa;QAClB,YAAY,EAAE,EAAE,CAAC,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC,EAAE,CAAC;QACnC,WAAW,EAAE,EAAE,CAAC,EAAE,CAAC,KAAK,IAAI,EAAE;YAC7B,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;QACpD,CAAC,CAAC;KACF,CAAC;IAEF,MAAM,OAAO,GAAG,MAAM,wBAAwB,CAAC;QAC9C,EAAE,EAAE,EAAS;QACb,IAAI,EAAE,iBAAiB;QACvB,cAAc,EAAE,CAAC,UAAU,CAAC;KAC5B,CAAC,CAAC;IAEH,MAAM,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,gBAAgB,EAAE,CAAC;IAClD,MAAM,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;AACxD,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,4IAA4I,EAAE,KAAK,IAAI,EAAE;IAC7J,MAAM,QAAQ,GAAG;QAChB,+BAA+B,EAAE,IAAI,CAAC,SAAS,CAAC;YAC/C,UAAU,EAAE,IAAI;YAChB,OAAO,EAAE,CAAC,IAAI,CAAC;YACf,OAAO,EAAE,EAAE;SACe,CAAC;KAC5B,CAAC;IAEF,MAAM,EAAE,GAAG,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAErC,MAAM,WAAW,GAAiB;QACjC,GAAG,EAAE,cAAc;QACnB,YAAY,EAAE,EAAE,CAAC,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC,EAAE,CAAC;QACnC,WAAW,EAAE,EAAE,CAAC,EAAE,CAAC,KAAK,IAAI,EAAE;YAC7B,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;QACpD,CAAC,CAAC;KACF,CAAC;IAEF,MAAM,WAAW,GAAiB;QACjC,GAAG,EAAE,cAAc;QACnB,YAAY,EAAE,EAAE,CAAC,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC,EAAE,CAAC;QACnC,WAAW,EAAE,EAAE,CAAC,EAAE,CAAC,KAAK,IAAI,EAAE;YAC7B,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;QACpD,CAAC,CAAC;KACF,CAAC;IAEF,MAAM,OAAO,GAAG,MAAM,wBAAwB,CAAC;QAC9C,EAAE,EAAE,EAAS;QACb,IAAI,EAAE,iBAAiB;QACvB,cAAc,EAAE,CAAC,WAAW,EAAE,WAAW,CAAC;KAC1C,CAAC,CAAC;IAEH,MAAM,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC,gBAAgB,EAAE,CAAC;IACnD,MAAM,CAAC,WAAW,CAAC,YAAY,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;IAExD,MAAM,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC,gBAAgB,EAAE,CAAC;IACnD,MAAM,CAAC,WAAW,CAAC,YAAY,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;AACzD,CAAC,CAAC,CAAC","debug_id":"a2e360a7-8037-526f-b036-d39152e1fa8a"}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
|
|
2
|
-
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="
|
|
2
|
+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="80f53d9e-13de-5b36-ac28-4c5a7037b334")}catch(e){}}();
|
|
3
3
|
export const ENV_VARIABLES = {
|
|
4
4
|
PUBLIC_POSTHOG_TOKEN: "phc_m5yJZCxjOGxF8CJvP5sQ3H0d76xpnLrsmiZHduT4jDz",
|
|
5
5
|
PUBLIC_INLANG_SDK_SENTRY_DSN: "https://c3d92d5d011122e525e9f9b368e0905d@o4504345873285120.ingest.us.sentry.io/4507903389335553",
|
|
6
|
-
SDK_VERSION: "2.0.0-beta.
|
|
6
|
+
SDK_VERSION: "2.0.0-beta.6",
|
|
7
7
|
};
|
|
8
8
|
//# sourceMappingURL=index.js.map
|
|
9
|
-
//# debugId=
|
|
9
|
+
//# debugId=80f53d9e-13de-5b36-ac28-4c5a7037b334
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["services/env-variables/index.ts"],"sourceRoot":"/","sourcesContent":["\nexport const ENV_VARIABLES = {\n PUBLIC_POSTHOG_TOKEN: \"phc_m5yJZCxjOGxF8CJvP5sQ3H0d76xpnLrsmiZHduT4jDz\",\n\tPUBLIC_INLANG_SDK_SENTRY_DSN: \"https://c3d92d5d011122e525e9f9b368e0905d@o4504345873285120.ingest.us.sentry.io/4507903389335553\",\n\tSDK_VERSION: \"2.0.0-beta.
|
|
1
|
+
{"version":3,"file":"index.js","sources":["services/env-variables/index.ts"],"sourceRoot":"/","sourcesContent":["\nexport const ENV_VARIABLES = {\n PUBLIC_POSTHOG_TOKEN: \"phc_m5yJZCxjOGxF8CJvP5sQ3H0d76xpnLrsmiZHduT4jDz\",\n\tPUBLIC_INLANG_SDK_SENTRY_DSN: \"https://c3d92d5d011122e525e9f9b368e0905d@o4504345873285120.ingest.us.sentry.io/4507903389335553\",\n\tSDK_VERSION: \"2.0.0-beta.6\",\n}\n"],"names":[],"mappings":";;AACA,MAAM,CAAC,MAAM,aAAa,GAAG;IAC3B,oBAAoB,EAAE,iDAAiD;IACxE,4BAA4B,EAAE,iGAAiG;IAC/H,WAAW,EAAE,cAAc;CAC3B,CAAA","debug_id":"80f53d9e-13de-5b36-ac28-4c5a7037b334"}
|
package/package.json
CHANGED
|
@@ -658,7 +658,6 @@ test("it should pass toBeImportedMetadata on import", async () => {
|
|
|
658
658
|
expect.objectContaining({
|
|
659
659
|
files: [
|
|
660
660
|
expect.objectContaining({
|
|
661
|
-
name: "en.json",
|
|
662
661
|
toBeImportedFilesMetadata: {
|
|
663
662
|
foo: "bar",
|
|
664
663
|
},
|
|
@@ -852,3 +851,72 @@ test("it can import plugins via http", async () => {
|
|
|
852
851
|
"expecting the plugin to be cached"
|
|
853
852
|
).toBe(true);
|
|
854
853
|
});
|
|
854
|
+
|
|
855
|
+
test("plugins that provide both loadMessages and importFiles should be allowed and the importFiles should be called", async () => {
|
|
856
|
+
const mockRepo = {
|
|
857
|
+
"/project.inlang/settings.json": JSON.stringify({
|
|
858
|
+
baseLocale: "en",
|
|
859
|
+
locales: ["en"],
|
|
860
|
+
modules: [],
|
|
861
|
+
} satisfies ProjectSettings),
|
|
862
|
+
};
|
|
863
|
+
|
|
864
|
+
const fs = Volume.fromJSON(mockRepo);
|
|
865
|
+
|
|
866
|
+
const mockPlugin: InlangPlugin = {
|
|
867
|
+
key: "mock-plugin",
|
|
868
|
+
loadMessages: vi.fn(async () => []),
|
|
869
|
+
importFiles: vi.fn(async () => {
|
|
870
|
+
return { bundles: [], messages: [], variants: [] };
|
|
871
|
+
}),
|
|
872
|
+
};
|
|
873
|
+
|
|
874
|
+
const project = await loadProjectFromDirectory({
|
|
875
|
+
fs: fs as any,
|
|
876
|
+
path: "/project.inlang",
|
|
877
|
+
providePlugins: [mockPlugin],
|
|
878
|
+
});
|
|
879
|
+
|
|
880
|
+
expect(mockPlugin.importFiles).toHaveBeenCalled();
|
|
881
|
+
expect(mockPlugin.loadMessages).not.toHaveBeenCalled();
|
|
882
|
+
});
|
|
883
|
+
|
|
884
|
+
test("providing multiple plugins that have legacy loadMessages and saveMessages function should be possible if they have import/export functions", async () => {
|
|
885
|
+
const mockRepo = {
|
|
886
|
+
"/project.inlang/settings.json": JSON.stringify({
|
|
887
|
+
baseLocale: "en",
|
|
888
|
+
locales: ["en"],
|
|
889
|
+
modules: [],
|
|
890
|
+
} satisfies ProjectSettings),
|
|
891
|
+
};
|
|
892
|
+
|
|
893
|
+
const fs = Volume.fromJSON(mockRepo);
|
|
894
|
+
|
|
895
|
+
const mockPlugin1: InlangPlugin = {
|
|
896
|
+
key: "mock-plugin1",
|
|
897
|
+
loadMessages: vi.fn(async () => []),
|
|
898
|
+
importFiles: vi.fn(async () => {
|
|
899
|
+
return { bundles: [], messages: [], variants: [] };
|
|
900
|
+
}),
|
|
901
|
+
};
|
|
902
|
+
|
|
903
|
+
const mockPlugin2: InlangPlugin = {
|
|
904
|
+
key: "mock-plugin2",
|
|
905
|
+
loadMessages: vi.fn(async () => []),
|
|
906
|
+
importFiles: vi.fn(async () => {
|
|
907
|
+
return { bundles: [], messages: [], variants: [] };
|
|
908
|
+
}),
|
|
909
|
+
};
|
|
910
|
+
|
|
911
|
+
const project = await loadProjectFromDirectory({
|
|
912
|
+
fs: fs as any,
|
|
913
|
+
path: "/project.inlang",
|
|
914
|
+
providePlugins: [mockPlugin1, mockPlugin2],
|
|
915
|
+
});
|
|
916
|
+
|
|
917
|
+
expect(mockPlugin1.importFiles).toHaveBeenCalled();
|
|
918
|
+
expect(mockPlugin1.loadMessages).not.toHaveBeenCalled();
|
|
919
|
+
|
|
920
|
+
expect(mockPlugin2.importFiles).toHaveBeenCalled();
|
|
921
|
+
expect(mockPlugin2.loadMessages).not.toHaveBeenCalled();
|
|
922
|
+
});
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import { newProject } from "./newProject.js";
|
|
2
2
|
import { loadProjectInMemory } from "./loadProjectInMemory.js";
|
|
3
3
|
import { type Lix } from "@lix-js/sdk";
|
|
4
|
-
|
|
5
4
|
import fs from "node:fs";
|
|
6
|
-
|
|
7
5
|
import nodePath from "node:path";
|
|
8
6
|
import type {
|
|
9
7
|
InlangPlugin,
|
|
@@ -14,6 +12,7 @@ import type { ProjectSettings } from "../json-schema/settings.js";
|
|
|
14
12
|
import type { PreprocessPluginBeforeImportFunction } from "../plugin/importPlugins.js";
|
|
15
13
|
import { PluginImportError } from "../plugin/errors.js";
|
|
16
14
|
import { upsertBundleNestedMatchByProperties } from "../import-export/upsertBundleNestedMatchByProperties.js";
|
|
15
|
+
import type { ImportFile } from "./api.js";
|
|
17
16
|
|
|
18
17
|
/**
|
|
19
18
|
* Loads a project from a directory.
|
|
@@ -62,69 +61,39 @@ export async function loadProjectFromDirectory(
|
|
|
62
61
|
syncInterval: args.syncInterval,
|
|
63
62
|
});
|
|
64
63
|
|
|
65
|
-
const
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
importPlugins,
|
|
69
|
-
exportPlugins,
|
|
70
|
-
} = categorizePlugins(await project.plugins.get());
|
|
64
|
+
const allPlugins = await project.plugins.get();
|
|
65
|
+
const { loadSavePlugins, importExportPlugins } =
|
|
66
|
+
categorizePlugins(allPlugins);
|
|
71
67
|
|
|
72
68
|
// TODO i guess we should move this validation logic into sdk2/src/project/loadProject.ts
|
|
73
69
|
// Two scenarios could arise:
|
|
74
70
|
// 1. set settings is called from an app - it should detect and reject the setting of settings -> app need to be able to validate before calling set
|
|
75
71
|
// 2. the settings file loaded from disc here is corrupted -> user has to fix the file on disc
|
|
76
|
-
if (
|
|
72
|
+
if (loadSavePlugins.length > 1) {
|
|
77
73
|
throw new Error(
|
|
78
74
|
"Max one loadMessages (found: " +
|
|
79
|
-
|
|
75
|
+
loadSavePlugins.length +
|
|
80
76
|
") and one saveMessages plugins (found: " +
|
|
81
|
-
|
|
77
|
+
loadSavePlugins.length +
|
|
82
78
|
") are allowed "
|
|
83
79
|
);
|
|
84
80
|
}
|
|
85
81
|
const importedResourceFileErrors: Error[] = [];
|
|
86
82
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
"Plugins for loadMessages (found: " +
|
|
93
|
-
loadMessagesPlugins.length +
|
|
94
|
-
") and saveMessages plugins (found: " +
|
|
95
|
-
saveMessagesPlugins.length +
|
|
96
|
-
") must not coexist with import (found: " +
|
|
97
|
-
importPlugins.length +
|
|
98
|
-
") or export (found: " +
|
|
99
|
-
exportPlugins.length +
|
|
100
|
-
") "
|
|
101
|
-
);
|
|
102
|
-
} else if (loadMessagesPlugins.length > 1 || saveMessagesPlugins.length > 1) {
|
|
103
|
-
throw new Error(
|
|
104
|
-
"Max one loadMessages (found: " +
|
|
105
|
-
loadMessagesPlugins.length +
|
|
106
|
-
") and one saveMessages plugins (found: " +
|
|
107
|
-
saveMessagesPlugins.length +
|
|
108
|
-
") are allowed "
|
|
109
|
-
);
|
|
110
|
-
} else if (importPlugins[0]) {
|
|
111
|
-
const importer = importPlugins[0];
|
|
112
|
-
const files = [];
|
|
113
|
-
|
|
114
|
-
if (importer.toBeImportedFiles) {
|
|
115
|
-
const toBeImportedFiles = await importer.toBeImportedFiles({
|
|
83
|
+
// import files from local fs
|
|
84
|
+
for (const plugin of importExportPlugins) {
|
|
85
|
+
const files: ImportFile[] = [];
|
|
86
|
+
if (plugin.toBeImportedFiles) {
|
|
87
|
+
const toBeImportedFiles = await plugin.toBeImportedFiles({
|
|
116
88
|
settings: await project.settings.get(),
|
|
117
89
|
});
|
|
118
90
|
for (const toBeImported of toBeImportedFiles) {
|
|
119
91
|
const absolute = absolutePathFromProject(args.path, toBeImported.path);
|
|
120
92
|
try {
|
|
121
93
|
const data = await args.fs.promises.readFile(absolute);
|
|
122
|
-
const name = nodePath.basename(toBeImported.path);
|
|
123
94
|
files.push({
|
|
124
|
-
name,
|
|
125
95
|
locale: toBeImported.locale,
|
|
126
96
|
content: data,
|
|
127
|
-
pluginKey: importer.key,
|
|
128
97
|
toBeImportedFilesMetadata: toBeImported.metadata,
|
|
129
98
|
});
|
|
130
99
|
} catch (e) {
|
|
@@ -143,17 +112,18 @@ export async function loadProjectFromDirectory(
|
|
|
143
112
|
}
|
|
144
113
|
|
|
145
114
|
await project.importFiles({
|
|
146
|
-
pluginKey:
|
|
147
|
-
files
|
|
115
|
+
pluginKey: plugin.key,
|
|
116
|
+
files,
|
|
148
117
|
});
|
|
149
|
-
}
|
|
150
|
-
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
for (const plugin of loadSavePlugins) {
|
|
151
121
|
await loadLegacyMessages({
|
|
152
122
|
project,
|
|
123
|
+
pluginKey: plugin.key ?? plugin.id,
|
|
124
|
+
loadMessagesFn: plugin.loadMessages!,
|
|
153
125
|
projectPath: args.path,
|
|
154
126
|
fs: args.fs,
|
|
155
|
-
pluginKey: loadMessagesPlugins[0].key ?? loadMessagesPlugins[0].id,
|
|
156
|
-
loadMessagesFn: loadMessagesPlugins[0].loadMessages,
|
|
157
127
|
});
|
|
158
128
|
}
|
|
159
129
|
|
|
@@ -583,52 +553,28 @@ async function upsertFileInLix(
|
|
|
583
553
|
)
|
|
584
554
|
.execute();
|
|
585
555
|
}
|
|
556
|
+
/**
|
|
557
|
+
* Filters legacy load and save messages plugins.
|
|
558
|
+
*
|
|
559
|
+
* Legacy plugins are plugins that implement loadMessages and saveMessages but not importFiles and exportFiles.
|
|
560
|
+
*/
|
|
561
|
+
function categorizePlugins(plugins: readonly InlangPlugin[]) {
|
|
562
|
+
const loadSavePlugins: InlangPlugin[] = [];
|
|
563
|
+
const importExportPlugins: InlangPlugin[] = [];
|
|
564
|
+
|
|
565
|
+
for (const plugin of plugins) {
|
|
566
|
+
if (
|
|
567
|
+
plugin.loadMessages &&
|
|
568
|
+
plugin.saveMessages &&
|
|
569
|
+
!(plugin.importFiles && plugin.exportFiles)
|
|
570
|
+
) {
|
|
571
|
+
loadSavePlugins.push(plugin);
|
|
572
|
+
} else if (plugin.importFiles || plugin.exportFiles) {
|
|
573
|
+
importExportPlugins.push(plugin);
|
|
574
|
+
}
|
|
575
|
+
}
|
|
586
576
|
|
|
587
|
-
|
|
588
|
-
function categorizePlugins(plugins: readonly InlangPlugin[]): {
|
|
589
|
-
loadMessagesPlugins: (InlangPlugin &
|
|
590
|
-
Required<Pick<InlangPlugin, "loadMessages">>)[];
|
|
591
|
-
saveMessagesPlugins: (InlangPlugin &
|
|
592
|
-
Required<Pick<InlangPlugin, "saveMessages">>)[];
|
|
593
|
-
importPlugins: (InlangPlugin &
|
|
594
|
-
Required<Pick<InlangPlugin, "importFiles" | "toBeImportedFiles">>)[];
|
|
595
|
-
exportPlugins: (InlangPlugin & Required<Pick<InlangPlugin, "exportFiles">>)[];
|
|
596
|
-
} {
|
|
597
|
-
const loadMessagesPlugins = plugins.filter(
|
|
598
|
-
(
|
|
599
|
-
plugin
|
|
600
|
-
): plugin is InlangPlugin & Required<Pick<InlangPlugin, "loadMessages">> =>
|
|
601
|
-
plugin.loadMessages !== undefined
|
|
602
|
-
);
|
|
603
|
-
|
|
604
|
-
const saveMessagesPlugins = plugins.filter(
|
|
605
|
-
(
|
|
606
|
-
plugin
|
|
607
|
-
): plugin is InlangPlugin & Required<Pick<InlangPlugin, "saveMessages">> =>
|
|
608
|
-
plugin.saveMessages !== undefined
|
|
609
|
-
);
|
|
610
|
-
|
|
611
|
-
const importPlugins = plugins.filter(
|
|
612
|
-
(
|
|
613
|
-
plugin
|
|
614
|
-
): plugin is InlangPlugin &
|
|
615
|
-
Required<Pick<InlangPlugin, "importFiles" | "toBeImportedFiles">> =>
|
|
616
|
-
plugin.importFiles !== undefined && plugin.toBeImportedFiles !== undefined
|
|
617
|
-
);
|
|
618
|
-
|
|
619
|
-
const exportPlugins = plugins.filter(
|
|
620
|
-
(
|
|
621
|
-
plugin
|
|
622
|
-
): plugin is InlangPlugin & Required<Pick<InlangPlugin, "exportFiles">> =>
|
|
623
|
-
plugin.exportFiles !== undefined
|
|
624
|
-
);
|
|
625
|
-
|
|
626
|
-
return {
|
|
627
|
-
loadMessagesPlugins,
|
|
628
|
-
saveMessagesPlugins,
|
|
629
|
-
importPlugins,
|
|
630
|
-
exportPlugins,
|
|
631
|
-
};
|
|
577
|
+
return { loadSavePlugins, importExportPlugins };
|
|
632
578
|
}
|
|
633
579
|
|
|
634
580
|
/**
|