@inlang/sdk 2.2.0 → 2.2.1

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.
@@ -1 +1 @@
1
- {"version":3,"file":"importPlugins.d.ts","sourceRoot":"/","sources":["plugin/importPlugins.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAClE,OAAO,EAAE,WAAW,EAAqB,MAAM,aAAa,CAAC;AAC7D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAGhD;;;;GAIG;AACH,MAAM,MAAM,oCAAoC,GAAG,CAClD,UAAU,EAAE,MAAM,KACd,OAAO,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC;AAE9B,wBAAsB,aAAa,CAAC,IAAI,EAAE;IACzC,GAAG,EAAE,GAAG,CAAC;IACT,QAAQ,EAAE,eAAe,CAAC;IAC1B,4BAA4B,CAAC,EAAE,oCAAoC,CAAC;CACpE,GAAG,OAAO,CAAC;IACX,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,MAAM,EAAE,WAAW,EAAE,CAAC;CACtB,CAAC,CAyBD"}
1
+ {"version":3,"file":"importPlugins.d.ts","sourceRoot":"/","sources":["plugin/importPlugins.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAClE,OAAO,EAAE,WAAW,EAAqB,MAAM,aAAa,CAAC;AAC7D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAGhD;;;;GAIG;AACH,MAAM,MAAM,oCAAoC,GAAG,CAClD,UAAU,EAAE,MAAM,KACd,OAAO,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC;AAE9B,wBAAsB,aAAa,CAAC,IAAI,EAAE;IACzC,GAAG,EAAE,GAAG,CAAC;IACT,QAAQ,EAAE,eAAe,CAAC;IAC1B,4BAA4B,CAAC,EAAE,oCAAoC,CAAC;CACpE,GAAG,OAAO,CAAC;IACX,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,MAAM,EAAE,WAAW,EAAE,CAAC;CACtB,CAAC,CA+BD"}
@@ -9,9 +9,16 @@ export async function importPlugins(args) {
9
9
  if (args.preprocessPluginBeforeImport) {
10
10
  moduleAsText = await args.preprocessPluginBeforeImport(moduleAsText);
11
11
  }
12
- const moduleWithMimeType = "data:application/javascript," + encodeURIComponent(moduleAsText);
13
- const { default: module } = await import(
14
- /* @vite-ignore */ moduleWithMimeType);
12
+ let moduleAsURL;
13
+ if (process.versions.bun) {
14
+ // In bun we need to do dynamic imports differently
15
+ moduleAsURL = URL.createObjectURL(new Blob([moduleAsText], { type: "text/javascript" }));
16
+ }
17
+ else {
18
+ // node and others
19
+ moduleAsURL = "data:text/javascript;base64," + btoa(moduleAsText);
20
+ }
21
+ const { default: module } = await import(/* @vite-ignore */ moduleAsURL);
15
22
  // old legacy message lint rules are not supported
16
23
  // and ingored for backwards compatibility
17
24
  if (module.id?.includes("messageLintRule")) {
@@ -1 +1 @@
1
- {"version":3,"file":"importPlugins.js","sourceRoot":"/","sources":["plugin/importPlugins.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAE7D,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAWvC,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,IAInC;IAIA,MAAM,OAAO,GAAmB,EAAE,CAAC;IACnC,MAAM,MAAM,GAAkB,EAAE,CAAC;IACjC,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,IAAI,EAAE,EAAE,CAAC;QAC/C,IAAI,CAAC;YACJ,IAAI,YAAY,GAAG,MAAM,SAAS,CAAC,WAAW,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;YAC/D,IAAI,IAAI,CAAC,4BAA4B,EAAE,CAAC;gBACvC,YAAY,GAAG,MAAM,IAAI,CAAC,4BAA4B,CAAC,YAAY,CAAC,CAAC;YACtE,CAAC;YACD,MAAM,kBAAkB,GACvB,8BAA8B,GAAG,kBAAkB,CAAC,YAAY,CAAC,CAAC;YACnE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,MAAM,MAAM;YACvC,kBAAkB,CAAC,kBAAkB,CACrC,CAAC;YACF,kDAAkD;YAClD,0CAA0C;YAC1C,IAAI,MAAM,CAAC,EAAE,EAAE,QAAQ,CAAC,iBAAiB,CAAC,EAAE,CAAC;gBAC5C,SAAS;YACV,CAAC;YACD,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACtB,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACZ,MAAM,CAAC,IAAI,CAAC,IAAI,iBAAiB,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,CAAU,EAAE,CAAC,CAAC,CAAC;QACxE,CAAC;IACF,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;AAC5B,CAAC;AAED,KAAK,UAAU,WAAW,CAAC,GAAW;IACrC,IAAI,CAAC;QACJ,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,CAAC;QAClC,OAAO,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;IAC9B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,MAAM,IAAI,iBAAiB,CAAC;YAC3B,MAAM,EAAE,GAAG;YACX,KAAK,EAAE,KAAc;SACrB,CAAC,CAAC;IACJ,CAAC;AACF,CAAC","sourcesContent":["import type { Lix } from \"@lix-js/sdk\";\nimport type { ProjectSettings } from \"../json-schema/settings.js\";\nimport { PluginError, PluginImportError } from \"./errors.js\";\nimport type { InlangPlugin } from \"./schema.js\";\nimport { withCache } from \"./cache.js\";\n\n/**\n * Function that preprocesses the plugin before importing it.\n *\n * - used by sherlock to convert ESM to CJS\n */\nexport type PreprocessPluginBeforeImportFunction = (\n\tmoduleText: string\n) => Promise<string> | string;\n\nexport async function importPlugins(args: {\n\tlix: Lix;\n\tsettings: ProjectSettings;\n\tpreprocessPluginBeforeImport?: PreprocessPluginBeforeImportFunction;\n}): Promise<{\n\tplugins: InlangPlugin[];\n\terrors: PluginError[];\n}> {\n\tconst plugins: InlangPlugin[] = [];\n\tconst errors: PluginError[] = [];\n\tfor (const uri of args.settings.modules ?? []) {\n\t\ttry {\n\t\t\tlet moduleAsText = await withCache(fetchPlugin, args.lix)(uri);\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: module } = await import(\n\t\t\t\t/* @vite-ignore */ moduleWithMimeType\n\t\t\t);\n\t\t\t// old legacy message lint rules are not supported\n\t\t\t// and ingored for backwards compatibility\n\t\t\tif (module.id?.includes(\"messageLintRule\")) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tplugins.push(module);\n\t\t} catch (e) {\n\t\t\terrors.push(new PluginImportError({ plugin: uri, cause: e as Error }));\n\t\t}\n\t}\n\treturn { plugins, errors };\n}\n\nasync function fetchPlugin(uri: string): Promise<string> {\n\ttry {\n\t\tconst response = await fetch(uri);\n\t\treturn await response.text();\n\t} catch (error) {\n\t\tthrow new PluginImportError({\n\t\t\tplugin: uri,\n\t\t\tcause: error as Error,\n\t\t});\n\t}\n}\n"]}
1
+ {"version":3,"file":"importPlugins.js","sourceRoot":"/","sources":["plugin/importPlugins.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAE7D,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAWvC,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,IAInC;IAIA,MAAM,OAAO,GAAmB,EAAE,CAAC;IACnC,MAAM,MAAM,GAAkB,EAAE,CAAC;IACjC,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,IAAI,EAAE,EAAE,CAAC;QAC/C,IAAI,CAAC;YACJ,IAAI,YAAY,GAAG,MAAM,SAAS,CAAC,WAAW,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;YAC/D,IAAI,IAAI,CAAC,4BAA4B,EAAE,CAAC;gBACvC,YAAY,GAAG,MAAM,IAAI,CAAC,4BAA4B,CAAC,YAAY,CAAC,CAAC;YACtE,CAAC;YACD,IAAI,WAAW,CAAC;YAChB,IAAI,OAAO,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC;gBAC1B,mDAAmD;gBACnD,WAAW,GAAG,GAAG,CAAC,eAAe,CAChC,IAAI,IAAI,CAAC,CAAC,YAAY,CAAC,EAAE,EAAE,IAAI,EAAE,iBAAiB,EAAE,CAAC,CACrD,CAAC;YACH,CAAC;iBAAM,CAAC;gBACP,kBAAkB;gBAClB,WAAW,GAAG,8BAA8B,GAAG,IAAI,CAAC,YAAY,CAAC,CAAC;YACnE,CAAC;YACD,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,MAAM,MAAM,CAAC,kBAAkB,CAAC,WAAW,CAAC,CAAC;YACzE,kDAAkD;YAClD,0CAA0C;YAC1C,IAAI,MAAM,CAAC,EAAE,EAAE,QAAQ,CAAC,iBAAiB,CAAC,EAAE,CAAC;gBAC5C,SAAS;YACV,CAAC;YACD,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACtB,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACZ,MAAM,CAAC,IAAI,CAAC,IAAI,iBAAiB,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,CAAU,EAAE,CAAC,CAAC,CAAC;QACxE,CAAC;IACF,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;AAC5B,CAAC;AAED,KAAK,UAAU,WAAW,CAAC,GAAW;IACrC,IAAI,CAAC;QACJ,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,CAAC;QAClC,OAAO,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;IAC9B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,MAAM,IAAI,iBAAiB,CAAC;YAC3B,MAAM,EAAE,GAAG;YACX,KAAK,EAAE,KAAc;SACrB,CAAC,CAAC;IACJ,CAAC;AACF,CAAC","sourcesContent":["import type { Lix } from \"@lix-js/sdk\";\nimport type { ProjectSettings } from \"../json-schema/settings.js\";\nimport { PluginError, PluginImportError } from \"./errors.js\";\nimport type { InlangPlugin } from \"./schema.js\";\nimport { withCache } from \"./cache.js\";\n\n/**\n * Function that preprocesses the plugin before importing it.\n *\n * - used by sherlock to convert ESM to CJS\n */\nexport type PreprocessPluginBeforeImportFunction = (\n\tmoduleText: string\n) => Promise<string> | string;\n\nexport async function importPlugins(args: {\n\tlix: Lix;\n\tsettings: ProjectSettings;\n\tpreprocessPluginBeforeImport?: PreprocessPluginBeforeImportFunction;\n}): Promise<{\n\tplugins: InlangPlugin[];\n\terrors: PluginError[];\n}> {\n\tconst plugins: InlangPlugin[] = [];\n\tconst errors: PluginError[] = [];\n\tfor (const uri of args.settings.modules ?? []) {\n\t\ttry {\n\t\t\tlet moduleAsText = await withCache(fetchPlugin, args.lix)(uri);\n\t\t\tif (args.preprocessPluginBeforeImport) {\n\t\t\t\tmoduleAsText = await args.preprocessPluginBeforeImport(moduleAsText);\n\t\t\t}\n\t\t\tlet moduleAsURL;\n\t\t\tif (process.versions.bun) {\n\t\t\t\t// In bun we need to do dynamic imports differently\n\t\t\t\tmoduleAsURL = URL.createObjectURL(\n\t\t\t\t\tnew Blob([moduleAsText], { type: \"text/javascript\" })\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\t// node and others\n\t\t\t\tmoduleAsURL = \"data:text/javascript;base64,\" + btoa(moduleAsText);\n\t\t\t}\n\t\t\tconst { default: module } = await import(/* @vite-ignore */ moduleAsURL);\n\t\t\t// old legacy message lint rules are not supported\n\t\t\t// and ingored for backwards compatibility\n\t\t\tif (module.id?.includes(\"messageLintRule\")) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tplugins.push(module);\n\t\t} catch (e) {\n\t\t\terrors.push(new PluginImportError({ plugin: uri, cause: e as Error }));\n\t\t}\n\t}\n\treturn { plugins, errors };\n}\n\nasync function fetchPlugin(uri: string): Promise<string> {\n\ttry {\n\t\tconst response = await fetch(uri);\n\t\treturn await response.text();\n\t} catch (error) {\n\t\tthrow new PluginImportError({\n\t\t\tplugin: uri,\n\t\t\tcause: error as Error,\n\t\t});\n\t}\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"saveProjectToDirectory.d.ts","sourceRoot":"/","sources":["project/saveProjectToDirectory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACvC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAU9C,wBAAsB,sBAAsB,CAAC,IAAI,EAAE;IAClD,EAAE,EAAE,OAAO,EAAE,CAAC;IACd,OAAO,EAAE,aAAa,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;CACb,GAAG,OAAO,CAAC,IAAI,CAAC,CA8FhB"}
1
+ {"version":3,"file":"saveProjectToDirectory.d.ts","sourceRoot":"/","sources":["project/saveProjectToDirectory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACvC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAU9C,wBAAsB,sBAAsB,CAAC,IAAI,EAAE;IAClD,EAAE,EAAE,OAAO,EAAE,CAAC;IACd,OAAO,EAAE,aAAa,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;CACb,GAAG,OAAO,CAAC,IAAI,CAAC,CAgGhB"}
@@ -31,18 +31,6 @@ export async function saveProjectToDirectory(args) {
31
31
  const plugins = await args.project.plugins.get();
32
32
  const settings = await args.project.settings.get();
33
33
  for (const plugin of plugins) {
34
- // old legacy remove with v3
35
- if (plugin.saveMessages) {
36
- // in-efficient re-qeuery but it's a legacy function that will be removed.
37
- // the effort of adjusting the code to not re-query is not worth it.
38
- const bundlesNested = await selectBundleNested(args.project.db).execute();
39
- await plugin.saveMessages({
40
- messages: bundlesNested.map((b) => toMessageV1(b)),
41
- // @ts-expect-error - legacy
42
- nodeishFs: withAbsolutePaths(args.fs, args.path),
43
- settings,
44
- });
45
- }
46
34
  if (plugin.exportFiles) {
47
35
  const bundles = await args.project.db
48
36
  .selectFrom("bundle")
@@ -63,7 +51,10 @@ export async function saveProjectToDirectory(args) {
63
51
  settings,
64
52
  });
65
53
  for (const file of files) {
66
- const p = absolutePathFromProject(args.path, file.name);
54
+ const pathPattern = settings[plugin.key]?.pathPattern;
55
+ const p = pathPattern
56
+ ? pathPattern.replace(/\{(languageTag|locale)\}/g, file.locale)
57
+ : absolutePathFromProject(args.path, file.name);
67
58
  const dirname = path.dirname(p);
68
59
  if ((await args.fs.stat(dirname)).isDirectory() === false) {
69
60
  await args.fs.mkdir(dirname, { recursive: true });
@@ -85,6 +76,18 @@ export async function saveProjectToDirectory(args) {
85
76
  }
86
77
  }
87
78
  }
79
+ // old legacy remove with v3
80
+ else if (plugin.saveMessages) {
81
+ // in-efficient re-qeuery but it's a legacy function that will be removed.
82
+ // the effort of adjusting the code to not re-query is not worth it.
83
+ const bundlesNested = await selectBundleNested(args.project.db).execute();
84
+ await plugin.saveMessages({
85
+ messages: bundlesNested.map((b) => toMessageV1(b)),
86
+ // @ts-expect-error - legacy
87
+ nodeishFs: withAbsolutePaths(args.fs, args.path),
88
+ settings,
89
+ });
90
+ }
88
91
  }
89
92
  }
90
93
  //# sourceMappingURL=saveProjectToDirectory.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"saveProjectToDirectory.js","sourceRoot":"/","sources":["project/saveProjectToDirectory.ts"],"names":[],"mappings":"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","sourcesContent":["import type fs from \"node:fs/promises\";\nimport type { InlangProject } from \"./api.js\";\nimport path from \"node:path\";\nimport { toMessageV1 } from \"../json-schema/old-v1-message/toMessageV1.js\";\nimport {\n\tabsolutePathFromProject,\n\twithAbsolutePaths,\n} from \"./loadProjectFromDirectory.js\";\nimport { detectJsonFormatting } from \"../utilities/detectJsonFormatting.js\";\nimport { selectBundleNested } from \"../query-utilities/selectBundleNested.js\";\n\nexport async function saveProjectToDirectory(args: {\n\tfs: typeof fs;\n\tproject: InlangProject;\n\tpath: string;\n}): Promise<void> {\n\tif (args.path.endsWith(\".inlang\") === false) {\n\t\tthrow new Error(\"The path must end with .inlang\");\n\t}\n\tconst files = await args.project.lix.db\n\t\t.selectFrom(\"file\")\n\t\t.selectAll()\n\t\t.execute();\n\n\tlet hasGitignore = false;\n\n\t// write all files to the directory\n\tfor (const file of files) {\n\t\tif (file.path.endsWith(\"db.sqlite\")) {\n\t\t\tcontinue;\n\t\t} else if (file.path.endsWith(\".gitignore\")) {\n\t\t\thasGitignore = true;\n\t\t}\n\t\tconst p = path.join(args.path, file.path);\n\t\tawait args.fs.mkdir(path.dirname(p), { recursive: true });\n\t\tawait args.fs.writeFile(p, new Uint8Array(file.data));\n\t}\n\n\tif (hasGitignore === false) {\n\t\tawait args.fs.writeFile(\n\t\t\tpath.join(args.path, \".gitignore\"),\n\t\t\tnew TextEncoder().encode(\"cache\")\n\t\t);\n\t}\n\n\t// run exporters\n\tconst plugins = await args.project.plugins.get();\n\tconst settings = await args.project.settings.get();\n\n\tfor (const plugin of plugins) {\n\t\t// old legacy remove with v3\n\t\tif (plugin.saveMessages) {\n\t\t\t// in-efficient re-qeuery but it's a legacy function that will be removed.\n\t\t\t// the effort of adjusting the code to not re-query is not worth it.\n\t\t\tconst bundlesNested = await selectBundleNested(args.project.db).execute();\n\t\t\tawait plugin.saveMessages({\n\t\t\t\tmessages: bundlesNested.map((b) => toMessageV1(b)),\n\t\t\t\t// @ts-expect-error - legacy\n\t\t\t\tnodeishFs: withAbsolutePaths(args.fs, args.path),\n\t\t\t\tsettings,\n\t\t\t});\n\t\t}\n\n\t\tif (plugin.exportFiles) {\n\t\t\tconst bundles = await args.project.db\n\t\t\t\t.selectFrom(\"bundle\")\n\t\t\t\t.selectAll()\n\t\t\t\t.execute();\n\t\t\tconst messages = await args.project.db\n\t\t\t\t.selectFrom(\"message\")\n\t\t\t\t.selectAll()\n\t\t\t\t.execute();\n\t\t\tconst variants = await args.project.db\n\t\t\t\t.selectFrom(\"variant\")\n\t\t\t\t.selectAll()\n\t\t\t\t.execute();\n\t\t\tconst files = await plugin.exportFiles({\n\t\t\t\tbundles,\n\t\t\t\tmessages,\n\t\t\t\tvariants,\n\t\t\t\tsettings,\n\t\t\t});\n\t\t\tfor (const file of files) {\n\t\t\t\tconst p = absolutePathFromProject(args.path, file.name);\n\t\t\t\tconst dirname = path.dirname(p);\n\t\t\t\tif ((await args.fs.stat(dirname)).isDirectory() === false) {\n\t\t\t\t\tawait args.fs.mkdir(dirname, { recursive: true });\n\t\t\t\t}\n\t\t\t\tif (p.endsWith(\".json\")) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst existing = await args.fs.readFile(p, \"utf-8\");\n\t\t\t\t\t\tconst stringify = detectJsonFormatting(existing);\n\t\t\t\t\t\tawait args.fs.writeFile(\n\t\t\t\t\t\t\tp,\n\t\t\t\t\t\t\tnew TextEncoder().encode(\n\t\t\t\t\t\t\t\tstringify(JSON.parse(new TextDecoder().decode(file.content)))\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t);\n\t\t\t\t\t} catch {\n\t\t\t\t\t\t// write the file to disk (json doesn't exist yet)\n\t\t\t\t\t\t// yeah ugly duplication of write file but it works.\n\t\t\t\t\t\tawait args.fs.writeFile(p, new Uint8Array(file.content));\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tawait args.fs.writeFile(p, new Uint8Array(file.content));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n"]}
1
+ {"version":3,"file":"saveProjectToDirectory.js","sourceRoot":"/","sources":["project/saveProjectToDirectory.ts"],"names":[],"mappings":"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","sourcesContent":["import type fs from \"node:fs/promises\";\nimport type { InlangProject } from \"./api.js\";\nimport path from \"node:path\";\nimport { toMessageV1 } from \"../json-schema/old-v1-message/toMessageV1.js\";\nimport {\n\tabsolutePathFromProject,\n\twithAbsolutePaths,\n} from \"./loadProjectFromDirectory.js\";\nimport { detectJsonFormatting } from \"../utilities/detectJsonFormatting.js\";\nimport { selectBundleNested } from \"../query-utilities/selectBundleNested.js\";\n\nexport async function saveProjectToDirectory(args: {\n\tfs: typeof fs;\n\tproject: InlangProject;\n\tpath: string;\n}): Promise<void> {\n\tif (args.path.endsWith(\".inlang\") === false) {\n\t\tthrow new Error(\"The path must end with .inlang\");\n\t}\n\tconst files = await args.project.lix.db\n\t\t.selectFrom(\"file\")\n\t\t.selectAll()\n\t\t.execute();\n\n\tlet hasGitignore = false;\n\n\t// write all files to the directory\n\tfor (const file of files) {\n\t\tif (file.path.endsWith(\"db.sqlite\")) {\n\t\t\tcontinue;\n\t\t} else if (file.path.endsWith(\".gitignore\")) {\n\t\t\thasGitignore = true;\n\t\t}\n\t\tconst p = path.join(args.path, file.path);\n\t\tawait args.fs.mkdir(path.dirname(p), { recursive: true });\n\t\tawait args.fs.writeFile(p, new Uint8Array(file.data));\n\t}\n\n\tif (hasGitignore === false) {\n\t\tawait args.fs.writeFile(\n\t\t\tpath.join(args.path, \".gitignore\"),\n\t\t\tnew TextEncoder().encode(\"cache\")\n\t\t);\n\t}\n\n\t// run exporters\n\tconst plugins = await args.project.plugins.get();\n\tconst settings = await args.project.settings.get();\n\n\tfor (const plugin of plugins) {\n\t\tif (plugin.exportFiles) {\n\t\t\tconst bundles = await args.project.db\n\t\t\t\t.selectFrom(\"bundle\")\n\t\t\t\t.selectAll()\n\t\t\t\t.execute();\n\t\t\tconst messages = await args.project.db\n\t\t\t\t.selectFrom(\"message\")\n\t\t\t\t.selectAll()\n\t\t\t\t.execute();\n\t\t\tconst variants = await args.project.db\n\t\t\t\t.selectFrom(\"variant\")\n\t\t\t\t.selectAll()\n\t\t\t\t.execute();\n\t\t\tconst files = await plugin.exportFiles({\n\t\t\t\tbundles,\n\t\t\t\tmessages,\n\t\t\t\tvariants,\n\t\t\t\tsettings,\n\t\t\t});\n\t\t\tfor (const file of files) {\n\t\t\t\tconst pathPattern = settings[plugin.key]?.pathPattern;\n\t\t\t\tconst p = pathPattern\n\t\t\t\t\t? pathPattern.replace(/\\{(languageTag|locale)\\}/g, file.locale)\n\t\t\t\t\t: absolutePathFromProject(args.path, file.name);\n\t\t\t\tconst dirname = path.dirname(p);\n\t\t\t\tif ((await args.fs.stat(dirname)).isDirectory() === false) {\n\t\t\t\t\tawait args.fs.mkdir(dirname, { recursive: true });\n\t\t\t\t}\n\t\t\t\tif (p.endsWith(\".json\")) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst existing = await args.fs.readFile(p, \"utf-8\");\n\t\t\t\t\t\tconst stringify = detectJsonFormatting(existing);\n\t\t\t\t\t\tawait args.fs.writeFile(\n\t\t\t\t\t\t\tp,\n\t\t\t\t\t\t\tnew TextEncoder().encode(\n\t\t\t\t\t\t\t\tstringify(JSON.parse(new TextDecoder().decode(file.content)))\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t);\n\t\t\t\t\t} catch {\n\t\t\t\t\t\t// write the file to disk (json doesn't exist yet)\n\t\t\t\t\t\t// yeah ugly duplication of write file but it works.\n\t\t\t\t\t\tawait args.fs.writeFile(p, new Uint8Array(file.content));\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tawait args.fs.writeFile(p, new Uint8Array(file.content));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t// old legacy remove with v3\n\t\telse if (plugin.saveMessages) {\n\t\t\t// in-efficient re-qeuery but it's a legacy function that will be removed.\n\t\t\t// the effort of adjusting the code to not re-query is not worth it.\n\t\t\tconst bundlesNested = await selectBundleNested(args.project.db).execute();\n\t\t\tawait plugin.saveMessages({\n\t\t\t\tmessages: bundlesNested.map((b) => toMessageV1(b)),\n\t\t\t\t// @ts-expect-error - legacy\n\t\t\t\tnodeishFs: withAbsolutePaths(args.fs, args.path),\n\t\t\t\tsettings,\n\t\t\t});\n\t\t}\n\t}\n}\n"]}
@@ -252,4 +252,43 @@ test("adds a gitignore file if it doesn't exist", async () => {
252
252
  const gitignore = await fs.promises.readFile("/foo/bar.inlang/.gitignore", "utf-8");
253
253
  expect(gitignore).toBe("cache");
254
254
  });
255
+ test("uses exportFiles when both exportFiles and saveMessages are defined", async () => {
256
+ const exportFilesSpy = vi.fn().mockResolvedValue([]);
257
+ const saveMessagesSpy = vi.fn();
258
+ const mockPlugin = {
259
+ key: "mock",
260
+ exportFiles: exportFilesSpy,
261
+ saveMessages: saveMessagesSpy,
262
+ };
263
+ const volume = Volume.fromJSON({});
264
+ const project = await loadProjectInMemory({
265
+ blob: await newProject(),
266
+ providePlugins: [mockPlugin],
267
+ });
268
+ await saveProjectToDirectory({
269
+ path: "/foo/project.inlang",
270
+ fs: volume.promises,
271
+ project,
272
+ });
273
+ expect(exportFilesSpy).toHaveBeenCalled();
274
+ expect(saveMessagesSpy).not.toHaveBeenCalled();
275
+ });
276
+ test("uses saveMessages when exportFiles is not defined", async () => {
277
+ const saveMessagesSpy = vi.fn().mockResolvedValue([]);
278
+ const mockPlugin = {
279
+ key: "mock",
280
+ saveMessages: saveMessagesSpy,
281
+ };
282
+ const volume = Volume.fromJSON({});
283
+ const project = await loadProjectInMemory({
284
+ blob: await newProject(),
285
+ providePlugins: [mockPlugin],
286
+ });
287
+ await saveProjectToDirectory({
288
+ path: "/foo/project.inlang",
289
+ fs: volume.promises,
290
+ project,
291
+ });
292
+ expect(saveMessagesSpy).toHaveBeenCalled();
293
+ });
255
294
  //# sourceMappingURL=saveProjectToDirectory.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"saveProjectToDirectory.test.js","sourceRoot":"/","sources":["project/saveProjectToDirectory.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { test, expect, vi } from \"vitest\";\nimport { saveProjectToDirectory } from \"./saveProjectToDirectory.js\";\nimport { Volume } from \"memfs\";\nimport { loadProjectInMemory } from \"./loadProjectInMemory.js\";\nimport { newProject } from \"./newProject.js\";\nimport type { InlangPlugin } from \"../plugin/schema.js\";\nimport type { Bundle, NewMessage, Variant } from \"../database/schema.js\";\nimport { loadProjectFromDirectory } from \"./loadProjectFromDirectory.js\";\nimport { selectBundleNested } from \"../query-utilities/selectBundleNested.js\";\nimport type { ProjectSettings } from \"../json-schema/settings.js\";\nimport type { MessageV1 } from \"../json-schema/old-v1-message/schemaV1.js\";\n\ntest(\"it should throw if the path doesn't end with .inlang\", async () => {\n\tawait expect(() =>\n\t\tsaveProjectToDirectory({\n\t\t\tfs: {} as any,\n\t\t\tproject: {} as any,\n\t\t\tpath: \"/foo/bar\",\n\t\t})\n\t).rejects.toThrowError(\"The path must end with .inlang\");\n});\n\ntest(\"it should overwrite all files to the directory except the db.sqlite file\", async () => {\n\tconst mockFs = Volume.fromJSON({\n\t\t\"/foo/bar.inlang/settings.json\": JSON.stringify({\n\t\t\tbaseLocale: \"en\",\n\t\t\tlocales: [\"en\"],\n\t\t}),\n\t}).promises as any;\n\n\tconst project = await loadProjectInMemory({\n\t\tblob: await newProject({\n\t\t\tsettings: {\n\t\t\t\tbaseLocale: \"en\",\n\t\t\t\tlocales: [\"en\", \"fr\", \"mock\"],\n\t\t\t},\n\t\t}),\n\t});\n\n\tawait saveProjectToDirectory({\n\t\tfs: mockFs,\n\t\tproject,\n\t\tpath: \"/foo/bar.inlang\",\n\t});\n\n\tconst files = await mockFs.readdir(\"/foo/bar.inlang\");\n\tconst updatedSettingsFile = await mockFs.readFile(\n\t\t\"/foo/bar.inlang/settings.json\",\n\t\t\"utf-8\"\n\t);\n\tconst updatedSettings = JSON.parse(updatedSettingsFile);\n\n\t// only testing known files at the time of the test.\n\t// this test should be updated for files that should NOT\n\t// be contained in the directory in the future\n\texpect(files).toContain(\"settings.json\");\n\texpect(files).not.toContain(\"db.sqlite\");\n\texpect(updatedSettings.baseLocale).toBe(\"en\");\n\texpect(updatedSettings.locales).toEqual([\"en\", \"fr\", \"mock\"]);\n});\n\ntest(\"a roundtrip should work\", async () => {\n\tconst bundles: Bundle[] = [{ id: \"mock-bundle\", declarations: [] }];\n\tconst messages: NewMessage[] = [{ bundleId: \"mock-bundle\", locale: \"en\" }];\n\tconst variants: Variant[] = [];\n\n\tconst volume = Volume.fromJSON({\n\t\t\"/mock-file.json\": JSON.stringify({ bundles, messages, variants }),\n\t});\n\n\tconst mockPlugin: InlangPlugin = {\n\t\tkey: \"mock-plugin\",\n\t\ttoBeImportedFiles: async () => {\n\t\t\treturn [{ path: \"/mock-file.json\", locale: \"mock\" }];\n\t\t},\n\t\timportFiles: async ({ files }) => {\n\t\t\tconst { bundles, messages, variants } = JSON.parse(\n\t\t\t\tnew TextDecoder().decode(files[0]?.content)\n\t\t\t);\n\t\t\treturn { bundles, messages, variants };\n\t\t},\n\t\texportFiles: async ({ bundles }) => {\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\tcontent: new TextEncoder().encode(JSON.stringify(bundles)),\n\t\t\t\t\tname: \"mock-file.json\",\n\t\t\t\t\tlocale: \"mock\",\n\t\t\t\t},\n\t\t\t];\n\t\t},\n\t};\n\n\tconst exportFilesSpy = vi.spyOn(mockPlugin, \"exportFiles\");\n\tconst importFilesSpy = vi.spyOn(mockPlugin, \"importFiles\");\n\n\tconst project = await loadProjectInMemory({\n\t\tblob: await newProject(),\n\t\tprovidePlugins: [mockPlugin],\n\t});\n\n\tawait project.db.insertInto(\"bundle\").values(bundles).execute();\n\tawait project.db.insertInto(\"message\").values(messages).execute();\n\n\tawait saveProjectToDirectory({\n\t\tfs: volume.promises as any,\n\t\tproject,\n\t\tpath: \"/foo/bar.inlang\",\n\t});\n\n\t// const fileTree = volume.toJSON();\n\n\texpect(exportFilesSpy).toHaveBeenCalled();\n\texpect(importFilesSpy).not.toHaveBeenCalled();\n\n\t// TODO deactivated since mockBundleNested no longer contains the id of the messages\n\t// expect(fileTree).toEqual(\n\t// \texpect.objectContaining({\n\t// \t\t\"/foo/mock-file.json\": JSON.stringify([mockBundleNested]),\n\t// \t})\n\t// );\n\n\t// testing roundtrip\n\n\tconst project2 = await loadProjectFromDirectory({\n\t\tfs: volume as any,\n\t\tpath: \"/foo/bar.inlang\",\n\t\tprovidePlugins: [mockPlugin],\n\t});\n\n\texpect(mockPlugin.importFiles).toHaveBeenCalled();\n\n\tconst bundlesAfter = await project2.db\n\t\t.selectFrom(\"bundle\")\n\t\t.selectAll()\n\t\t.execute();\n\tconst messagesAfter = await project2.db\n\t\t.selectFrom(\"message\")\n\t\t.selectAll()\n\t\t.execute();\n\tconst variantsAfter = await project2.db\n\t\t.selectFrom(\"variant\")\n\t\t.selectAll()\n\t\t.execute();\n\n\texpect(bundlesAfter).lengthOf(1);\n\texpect(messagesAfter).lengthOf(1);\n\texpect(variantsAfter).lengthOf(0);\n\n\texpect(bundlesAfter[0]).toStrictEqual(expect.objectContaining(bundles[0]));\n\texpect(messagesAfter[0]).toStrictEqual(\n\t\texpect.objectContaining(messagesAfter[0])\n\t);\n});\n\ntest.todo(\n\t\"a roundtrip with legacy load and save messages should work\",\n\tasync () => {\n\t\tconst mockMessageV1: MessageV1 = {\n\t\t\tid: \"mock-legacy-message\",\n\t\t\talias: {},\n\t\t\tselectors: [],\n\t\t\tvariants: [\n\t\t\t\t{\n\t\t\t\t\tlanguageTag: \"en\",\n\t\t\t\t\tmatch: [],\n\t\t\t\t\tpattern: [{ type: \"Text\", value: \"Hello from legacy message\" }],\n\t\t\t\t},\n\t\t\t],\n\t\t};\n\n\t\tconst volume = Volume.fromJSON({\n\t\t\t\"/foo/bar.inlang/settings.json\": JSON.stringify({\n\t\t\t\tbaseLocale: \"en\",\n\t\t\t\tlocales: [\"en\"],\n\t\t\t} satisfies ProjectSettings),\n\t\t\t\"/foo/i18n/en.json\": JSON.stringify([mockMessageV1]),\n\t\t});\n\n\t\tconst mockPlugin: InlangPlugin = {\n\t\t\tid: \"mock-legacy-plugin\",\n\t\t\tkey: \"mock-legacy-plugin\",\n\t\t\tloadMessages: async ({ nodeishFs }) => {\n\t\t\t\t// expecting `loadMessages` to transform the relative path\n\t\t\t\t// to an absolute path `./i18n/en.json` -> `/foo/i18n/en.json`\n\t\t\t\tconst file = await nodeishFs.readFile(\"./i18n/en.json\", {\n\t\t\t\t\tencoding: \"utf-8\",\n\t\t\t\t});\n\t\t\t\treturn JSON.parse(file as string);\n\t\t\t},\n\t\t\tsaveMessages: async ({ messages, nodeishFs }) => {\n\t\t\t\tawait nodeishFs.writeFile(\n\t\t\t\t\t\"./i18n/en.json\",\n\t\t\t\t\tnew TextEncoder().encode(JSON.stringify(messages))\n\t\t\t\t\t\t.buffer as ArrayBuffer\n\t\t\t\t);\n\t\t\t},\n\t\t};\n\n\t\tconst loadMessagesSpy = vi.spyOn(mockPlugin, \"loadMessages\");\n\t\tconst saveMessagesSpy = vi.spyOn(mockPlugin, \"saveMessages\");\n\n\t\tconst project = await loadProjectFromDirectory({\n\t\t\tfs: volume as any,\n\t\t\tpath: \"/foo/bar.inlang\",\n\t\t\tprovidePlugins: [mockPlugin],\n\t\t});\n\n\t\texpect(loadMessagesSpy).toHaveBeenCalled();\n\t\texpect(saveMessagesSpy).not.toHaveBeenCalled();\n\n\t\tconst bundles1 = await selectBundleNested(project.db).execute();\n\n\t\texpect(bundles1[0]?.messages).lengthOf(1);\n\t\texpect(bundles1[0]?.messages[0]?.variants).toEqual([\n\t\t\texpect.objectContaining({\n\t\t\t\tpattern: [\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: \"text\",\n\t\t\t\t\t\tvalue: \"Hello from legacy message\",\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t}),\n\t\t]);\n\n\t\t// await project.db\n\t\t// \t.updateTable(\"variant\")\n\t\t// \t.set({\n\t\t// \t\tpattern: [{ type: \"text\", value: \"Updated message\" }],\n\t\t// \t})\n\t\t// \t.where(\"id\", \"=\", bundles1[0]?.messages[0]?.variants[0]?.id as string)\n\t\t// \t.execute();\n\n\t\t// testing the saveMessages function by removing the en.json file\n\t\tawait volume.promises.rm(\"/foo/i18n/en.json\");\n\n\t\tawait saveProjectToDirectory({\n\t\t\tfs: volume.promises as any,\n\t\t\tproject,\n\t\t\tpath: \"/foo/bar.inlang\",\n\t\t});\n\n\t\texpect(saveMessagesSpy).toHaveBeenCalled();\n\n\t\tconst fileTree = volume.toJSON();\n\t\tconst parsed = JSON.parse(fileTree[\"/foo/i18n/en.json\"] as string);\n\n\t\texpect(parsed).toEqual(expect.objectContaining([mockMessageV1]));\n\n\t\t// testing roundtrip\n\n\t\tconst project2 = await loadProjectFromDirectory({\n\t\t\tfs: volume as any,\n\t\t\tpath: \"/foo/bar.inlang\",\n\t\t\tprovidePlugins: [mockPlugin],\n\t\t});\n\n\t\tconst bundles2 = await selectBundleNested(project2.db).execute();\n\n\t\t// TODO deactivated since the ids must not be equal for separate imports - matching happens on language and matcher now\n\t\texpect(bundles1).toStrictEqual(bundles2);\n\t}\n);\n\ntest(\"it should preserve the formatting of existing json resource files\", async () => {\n\tconst mockJson =\n\t\tJSON.stringify(\n\t\t\t{ key: \"value\" },\n\t\t\tundefined,\n\t\t\t// tab spacing\n\t\t\t\"\\t\"\n\t\t) +\n\t\t// ends with new line\n\t\t\"\\n\";\n\n\tconst mockPlugin: InlangPlugin = {\n\t\tkey: \"mock\",\n\t\texportFiles: async () => {\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\tname: \"en.json\",\n\t\t\t\t\t// no beautified json\n\t\t\t\t\tcontent: new TextEncoder().encode(JSON.stringify({ key: \"value\" })),\n\t\t\t\t\tlocale: \"en\",\n\t\t\t\t},\n\t\t\t];\n\t\t},\n\t};\n\n\tconst volume = Volume.fromJSON({\n\t\t\"/foo/project.inlang/settings.json\": JSON.stringify({\n\t\t\tbaseLocale: \"en\",\n\t\t\tlocales: [\"en\"],\n\t\t} satisfies ProjectSettings),\n\t\t\"/foo/en.json\": mockJson,\n\t});\n\n\tconst project = await loadProjectInMemory({\n\t\tblob: await newProject(),\n\t\tprovidePlugins: [mockPlugin],\n\t});\n\n\tawait saveProjectToDirectory({\n\t\tpath: \"/foo/project.inlang\",\n\t\tfs: volume.promises as any,\n\t\tproject,\n\t});\n\n\tconst fileAfterSave = await volume.promises.readFile(\"/foo/en.json\", \"utf-8\");\n\texpect(fileAfterSave).toBe(mockJson);\n});\n\ntest(\"adds a gitignore file if it doesn't exist\", async () => {\n\tconst fs = Volume.fromJSON({});\n\n\tconst project = await loadProjectInMemory({\n\t\tblob: await newProject(),\n\t});\n\n\tawait saveProjectToDirectory({\n\t\tfs: fs.promises as any,\n\t\tproject,\n\t\tpath: \"/foo/bar.inlang\",\n\t});\n\n\tconst gitignore = await fs.promises.readFile(\n\t\t\"/foo/bar.inlang/.gitignore\",\n\t\t\"utf-8\"\n\t);\n\texpect(gitignore).toBe(\"cache\");\n});\n"]}
1
+ {"version":3,"file":"saveProjectToDirectory.test.js","sourceRoot":"/","sources":["project/saveProjectToDirectory.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { test, expect, vi } from \"vitest\";\nimport { saveProjectToDirectory } from \"./saveProjectToDirectory.js\";\nimport { Volume } from \"memfs\";\nimport { loadProjectInMemory } from \"./loadProjectInMemory.js\";\nimport { newProject } from \"./newProject.js\";\nimport type { InlangPlugin } from \"../plugin/schema.js\";\nimport type { Bundle, NewMessage, Variant } from \"../database/schema.js\";\nimport { loadProjectFromDirectory } from \"./loadProjectFromDirectory.js\";\nimport { selectBundleNested } from \"../query-utilities/selectBundleNested.js\";\nimport type { ProjectSettings } from \"../json-schema/settings.js\";\nimport type { MessageV1 } from \"../json-schema/old-v1-message/schemaV1.js\";\n\ntest(\"it should throw if the path doesn't end with .inlang\", async () => {\n\tawait expect(() =>\n\t\tsaveProjectToDirectory({\n\t\t\tfs: {} as any,\n\t\t\tproject: {} as any,\n\t\t\tpath: \"/foo/bar\",\n\t\t})\n\t).rejects.toThrowError(\"The path must end with .inlang\");\n});\n\ntest(\"it should overwrite all files to the directory except the db.sqlite file\", async () => {\n\tconst mockFs = Volume.fromJSON({\n\t\t\"/foo/bar.inlang/settings.json\": JSON.stringify({\n\t\t\tbaseLocale: \"en\",\n\t\t\tlocales: [\"en\"],\n\t\t}),\n\t}).promises as any;\n\n\tconst project = await loadProjectInMemory({\n\t\tblob: await newProject({\n\t\t\tsettings: {\n\t\t\t\tbaseLocale: \"en\",\n\t\t\t\tlocales: [\"en\", \"fr\", \"mock\"],\n\t\t\t},\n\t\t}),\n\t});\n\n\tawait saveProjectToDirectory({\n\t\tfs: mockFs,\n\t\tproject,\n\t\tpath: \"/foo/bar.inlang\",\n\t});\n\n\tconst files = await mockFs.readdir(\"/foo/bar.inlang\");\n\tconst updatedSettingsFile = await mockFs.readFile(\n\t\t\"/foo/bar.inlang/settings.json\",\n\t\t\"utf-8\"\n\t);\n\tconst updatedSettings = JSON.parse(updatedSettingsFile);\n\n\t// only testing known files at the time of the test.\n\t// this test should be updated for files that should NOT\n\t// be contained in the directory in the future\n\texpect(files).toContain(\"settings.json\");\n\texpect(files).not.toContain(\"db.sqlite\");\n\texpect(updatedSettings.baseLocale).toBe(\"en\");\n\texpect(updatedSettings.locales).toEqual([\"en\", \"fr\", \"mock\"]);\n});\n\ntest(\"a roundtrip should work\", async () => {\n\tconst bundles: Bundle[] = [{ id: \"mock-bundle\", declarations: [] }];\n\tconst messages: NewMessage[] = [{ bundleId: \"mock-bundle\", locale: \"en\" }];\n\tconst variants: Variant[] = [];\n\n\tconst volume = Volume.fromJSON({\n\t\t\"/mock-file.json\": JSON.stringify({ bundles, messages, variants }),\n\t});\n\n\tconst mockPlugin: InlangPlugin = {\n\t\tkey: \"mock-plugin\",\n\t\ttoBeImportedFiles: async () => {\n\t\t\treturn [{ path: \"/mock-file.json\", locale: \"mock\" }];\n\t\t},\n\t\timportFiles: async ({ files }) => {\n\t\t\tconst { bundles, messages, variants } = JSON.parse(\n\t\t\t\tnew TextDecoder().decode(files[0]?.content)\n\t\t\t);\n\t\t\treturn { bundles, messages, variants };\n\t\t},\n\t\texportFiles: async ({ bundles }) => {\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\tcontent: new TextEncoder().encode(JSON.stringify(bundles)),\n\t\t\t\t\tname: \"mock-file.json\",\n\t\t\t\t\tlocale: \"mock\",\n\t\t\t\t},\n\t\t\t];\n\t\t},\n\t};\n\n\tconst exportFilesSpy = vi.spyOn(mockPlugin, \"exportFiles\");\n\tconst importFilesSpy = vi.spyOn(mockPlugin, \"importFiles\");\n\n\tconst project = await loadProjectInMemory({\n\t\tblob: await newProject(),\n\t\tprovidePlugins: [mockPlugin],\n\t});\n\n\tawait project.db.insertInto(\"bundle\").values(bundles).execute();\n\tawait project.db.insertInto(\"message\").values(messages).execute();\n\n\tawait saveProjectToDirectory({\n\t\tfs: volume.promises as any,\n\t\tproject,\n\t\tpath: \"/foo/bar.inlang\",\n\t});\n\n\t// const fileTree = volume.toJSON();\n\n\texpect(exportFilesSpy).toHaveBeenCalled();\n\texpect(importFilesSpy).not.toHaveBeenCalled();\n\n\t// TODO deactivated since mockBundleNested no longer contains the id of the messages\n\t// expect(fileTree).toEqual(\n\t// \texpect.objectContaining({\n\t// \t\t\"/foo/mock-file.json\": JSON.stringify([mockBundleNested]),\n\t// \t})\n\t// );\n\n\t// testing roundtrip\n\n\tconst project2 = await loadProjectFromDirectory({\n\t\tfs: volume as any,\n\t\tpath: \"/foo/bar.inlang\",\n\t\tprovidePlugins: [mockPlugin],\n\t});\n\n\texpect(mockPlugin.importFiles).toHaveBeenCalled();\n\n\tconst bundlesAfter = await project2.db\n\t\t.selectFrom(\"bundle\")\n\t\t.selectAll()\n\t\t.execute();\n\tconst messagesAfter = await project2.db\n\t\t.selectFrom(\"message\")\n\t\t.selectAll()\n\t\t.execute();\n\tconst variantsAfter = await project2.db\n\t\t.selectFrom(\"variant\")\n\t\t.selectAll()\n\t\t.execute();\n\n\texpect(bundlesAfter).lengthOf(1);\n\texpect(messagesAfter).lengthOf(1);\n\texpect(variantsAfter).lengthOf(0);\n\n\texpect(bundlesAfter[0]).toStrictEqual(expect.objectContaining(bundles[0]));\n\texpect(messagesAfter[0]).toStrictEqual(\n\t\texpect.objectContaining(messagesAfter[0])\n\t);\n});\n\ntest.todo(\n\t\"a roundtrip with legacy load and save messages should work\",\n\tasync () => {\n\t\tconst mockMessageV1: MessageV1 = {\n\t\t\tid: \"mock-legacy-message\",\n\t\t\talias: {},\n\t\t\tselectors: [],\n\t\t\tvariants: [\n\t\t\t\t{\n\t\t\t\t\tlanguageTag: \"en\",\n\t\t\t\t\tmatch: [],\n\t\t\t\t\tpattern: [{ type: \"Text\", value: \"Hello from legacy message\" }],\n\t\t\t\t},\n\t\t\t],\n\t\t};\n\n\t\tconst volume = Volume.fromJSON({\n\t\t\t\"/foo/bar.inlang/settings.json\": JSON.stringify({\n\t\t\t\tbaseLocale: \"en\",\n\t\t\t\tlocales: [\"en\"],\n\t\t\t} satisfies ProjectSettings),\n\t\t\t\"/foo/i18n/en.json\": JSON.stringify([mockMessageV1]),\n\t\t});\n\n\t\tconst mockPlugin: InlangPlugin = {\n\t\t\tid: \"mock-legacy-plugin\",\n\t\t\tkey: \"mock-legacy-plugin\",\n\t\t\tloadMessages: async ({ nodeishFs }) => {\n\t\t\t\t// expecting `loadMessages` to transform the relative path\n\t\t\t\t// to an absolute path `./i18n/en.json` -> `/foo/i18n/en.json`\n\t\t\t\tconst file = await nodeishFs.readFile(\"./i18n/en.json\", {\n\t\t\t\t\tencoding: \"utf-8\",\n\t\t\t\t});\n\t\t\t\treturn JSON.parse(file as string);\n\t\t\t},\n\t\t\tsaveMessages: async ({ messages, nodeishFs }) => {\n\t\t\t\tawait nodeishFs.writeFile(\n\t\t\t\t\t\"./i18n/en.json\",\n\t\t\t\t\tnew TextEncoder().encode(JSON.stringify(messages))\n\t\t\t\t\t\t.buffer as ArrayBuffer\n\t\t\t\t);\n\t\t\t},\n\t\t};\n\n\t\tconst loadMessagesSpy = vi.spyOn(mockPlugin, \"loadMessages\");\n\t\tconst saveMessagesSpy = vi.spyOn(mockPlugin, \"saveMessages\");\n\n\t\tconst project = await loadProjectFromDirectory({\n\t\t\tfs: volume as any,\n\t\t\tpath: \"/foo/bar.inlang\",\n\t\t\tprovidePlugins: [mockPlugin],\n\t\t});\n\n\t\texpect(loadMessagesSpy).toHaveBeenCalled();\n\t\texpect(saveMessagesSpy).not.toHaveBeenCalled();\n\n\t\tconst bundles1 = await selectBundleNested(project.db).execute();\n\n\t\texpect(bundles1[0]?.messages).lengthOf(1);\n\t\texpect(bundles1[0]?.messages[0]?.variants).toEqual([\n\t\t\texpect.objectContaining({\n\t\t\t\tpattern: [\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: \"text\",\n\t\t\t\t\t\tvalue: \"Hello from legacy message\",\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t}),\n\t\t]);\n\n\t\t// await project.db\n\t\t// \t.updateTable(\"variant\")\n\t\t// \t.set({\n\t\t// \t\tpattern: [{ type: \"text\", value: \"Updated message\" }],\n\t\t// \t})\n\t\t// \t.where(\"id\", \"=\", bundles1[0]?.messages[0]?.variants[0]?.id as string)\n\t\t// \t.execute();\n\n\t\t// testing the saveMessages function by removing the en.json file\n\t\tawait volume.promises.rm(\"/foo/i18n/en.json\");\n\n\t\tawait saveProjectToDirectory({\n\t\t\tfs: volume.promises as any,\n\t\t\tproject,\n\t\t\tpath: \"/foo/bar.inlang\",\n\t\t});\n\n\t\texpect(saveMessagesSpy).toHaveBeenCalled();\n\n\t\tconst fileTree = volume.toJSON();\n\t\tconst parsed = JSON.parse(fileTree[\"/foo/i18n/en.json\"] as string);\n\n\t\texpect(parsed).toEqual(expect.objectContaining([mockMessageV1]));\n\n\t\t// testing roundtrip\n\n\t\tconst project2 = await loadProjectFromDirectory({\n\t\t\tfs: volume as any,\n\t\t\tpath: \"/foo/bar.inlang\",\n\t\t\tprovidePlugins: [mockPlugin],\n\t\t});\n\n\t\tconst bundles2 = await selectBundleNested(project2.db).execute();\n\n\t\t// TODO deactivated since the ids must not be equal for separate imports - matching happens on language and matcher now\n\t\texpect(bundles1).toStrictEqual(bundles2);\n\t}\n);\n\ntest(\"it should preserve the formatting of existing json resource files\", async () => {\n\tconst mockJson =\n\t\tJSON.stringify(\n\t\t\t{ key: \"value\" },\n\t\t\tundefined,\n\t\t\t// tab spacing\n\t\t\t\"\\t\"\n\t\t) +\n\t\t// ends with new line\n\t\t\"\\n\";\n\n\tconst mockPlugin: InlangPlugin = {\n\t\tkey: \"mock\",\n\t\texportFiles: async () => {\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\tname: \"en.json\",\n\t\t\t\t\t// no beautified json\n\t\t\t\t\tcontent: new TextEncoder().encode(JSON.stringify({ key: \"value\" })),\n\t\t\t\t\tlocale: \"en\",\n\t\t\t\t},\n\t\t\t];\n\t\t},\n\t};\n\n\tconst volume = Volume.fromJSON({\n\t\t\"/foo/project.inlang/settings.json\": JSON.stringify({\n\t\t\tbaseLocale: \"en\",\n\t\t\tlocales: [\"en\"],\n\t\t} satisfies ProjectSettings),\n\t\t\"/foo/en.json\": mockJson,\n\t});\n\n\tconst project = await loadProjectInMemory({\n\t\tblob: await newProject(),\n\t\tprovidePlugins: [mockPlugin],\n\t});\n\n\tawait saveProjectToDirectory({\n\t\tpath: \"/foo/project.inlang\",\n\t\tfs: volume.promises as any,\n\t\tproject,\n\t});\n\n\tconst fileAfterSave = await volume.promises.readFile(\"/foo/en.json\", \"utf-8\");\n\texpect(fileAfterSave).toBe(mockJson);\n});\n\ntest(\"adds a gitignore file if it doesn't exist\", async () => {\n\tconst fs = Volume.fromJSON({});\n\n\tconst project = await loadProjectInMemory({\n\t\tblob: await newProject(),\n\t});\n\n\tawait saveProjectToDirectory({\n\t\tfs: fs.promises as any,\n\t\tproject,\n\t\tpath: \"/foo/bar.inlang\",\n\t});\n\n\tconst gitignore = await fs.promises.readFile(\n\t\t\"/foo/bar.inlang/.gitignore\",\n\t\t\"utf-8\"\n\t);\n\texpect(gitignore).toBe(\"cache\");\n});\n\n test(\"uses exportFiles when both exportFiles and saveMessages are defined\", async () => {\n\t\tconst exportFilesSpy = vi.fn().mockResolvedValue([]);\n\t\tconst saveMessagesSpy = vi.fn();\n\t\tconst mockPlugin: InlangPlugin = {\n\t\t\tkey: \"mock\",\n\t\t\texportFiles: exportFilesSpy,\n\t\t\tsaveMessages: saveMessagesSpy,\n\t\t};\n\t\tconst volume = Volume.fromJSON({});\n\t\tconst project = await loadProjectInMemory({\n\t\t\tblob: await newProject(),\n\t\t\tprovidePlugins: [mockPlugin],\n\t\t});\n\t\tawait saveProjectToDirectory({\n\t\t\tpath: \"/foo/project.inlang\",\n\t\t\tfs: volume.promises as any,\n\t\t\tproject,\n\t\t});\n\t\texpect(exportFilesSpy).toHaveBeenCalled();\n\t\texpect(saveMessagesSpy).not.toHaveBeenCalled();\n });\n\n test(\"uses saveMessages when exportFiles is not defined\", async () => {\n\t\tconst saveMessagesSpy = vi.fn().mockResolvedValue([]);\n\t\tconst mockPlugin: InlangPlugin = {\n\t\t\tkey: \"mock\",\n\t\t\tsaveMessages: saveMessagesSpy,\n\t\t};\n\t\tconst volume = Volume.fromJSON({});\n\t\tconst project = await loadProjectInMemory({\n\t\t\tblob: await newProject(),\n\t\t\tprovidePlugins: [mockPlugin],\n\t\t});\n\t\tawait saveProjectToDirectory({\n\t\t\tpath: \"/foo/project.inlang\",\n\t\t\tfs: volume.promises as any,\n\t\t\tproject,\n\t\t});\n\t\texpect(saveMessagesSpy).toHaveBeenCalled();\n });\n"]}
@@ -1,6 +1,6 @@
1
1
  export const ENV_VARIABLES = {
2
2
  PUBLIC_POSTHOG_TOKEN: "phc_m5yJZCxjOGxF8CJvP5sQ3H0d76xpnLrsmiZHduT4jDz",
3
3
  PUBLIC_INLANG_SDK_SENTRY_DSN: "https://c3d92d5d011122e525e9f9b368e0905d@o4504345873285120.ingest.us.sentry.io/4507903389335553",
4
- SDK_VERSION: "2.2.0",
4
+ SDK_VERSION: "2.2.1",
5
5
  };
6
6
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"/","sources":["services/env-variables/index.ts"],"names":[],"mappings":"AACA,MAAM,CAAC,MAAM,aAAa,GAAG;IAC3B,oBAAoB,EAAE,iDAAiD;IACxE,4BAA4B,EAAE,iGAAiG;IAC/H,WAAW,EAAE,OAAO;CACpB,CAAA","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.2.0\",\n}\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"/","sources":["services/env-variables/index.ts"],"names":[],"mappings":"AACA,MAAM,CAAC,MAAM,aAAa,GAAG;IAC3B,oBAAoB,EAAE,iDAAiD;IACxE,4BAA4B,EAAE,iGAAiG;IAC/H,WAAW,EAAE,OAAO;CACpB,CAAA","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.2.1\",\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inlang/sdk",
3
- "version": "2.2.0",
3
+ "version": "2.2.1",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "publishConfig": {
@@ -29,11 +29,17 @@ export async function importPlugins(args: {
29
29
  if (args.preprocessPluginBeforeImport) {
30
30
  moduleAsText = await args.preprocessPluginBeforeImport(moduleAsText);
31
31
  }
32
- const moduleWithMimeType =
33
- "data:application/javascript," + encodeURIComponent(moduleAsText);
34
- const { default: module } = await import(
35
- /* @vite-ignore */ moduleWithMimeType
36
- );
32
+ let moduleAsURL;
33
+ if (process.versions.bun) {
34
+ // In bun we need to do dynamic imports differently
35
+ moduleAsURL = URL.createObjectURL(
36
+ new Blob([moduleAsText], { type: "text/javascript" })
37
+ );
38
+ } else {
39
+ // node and others
40
+ moduleAsURL = "data:text/javascript;base64," + btoa(moduleAsText);
41
+ }
42
+ const { default: module } = await import(/* @vite-ignore */ moduleAsURL);
37
43
  // old legacy message lint rules are not supported
38
44
  // and ingored for backwards compatibility
39
45
  if (module.id?.includes("messageLintRule")) {
@@ -328,3 +328,44 @@ test("adds a gitignore file if it doesn't exist", async () => {
328
328
  );
329
329
  expect(gitignore).toBe("cache");
330
330
  });
331
+
332
+ test("uses exportFiles when both exportFiles and saveMessages are defined", async () => {
333
+ const exportFilesSpy = vi.fn().mockResolvedValue([]);
334
+ const saveMessagesSpy = vi.fn();
335
+ const mockPlugin: InlangPlugin = {
336
+ key: "mock",
337
+ exportFiles: exportFilesSpy,
338
+ saveMessages: saveMessagesSpy,
339
+ };
340
+ const volume = Volume.fromJSON({});
341
+ const project = await loadProjectInMemory({
342
+ blob: await newProject(),
343
+ providePlugins: [mockPlugin],
344
+ });
345
+ await saveProjectToDirectory({
346
+ path: "/foo/project.inlang",
347
+ fs: volume.promises as any,
348
+ project,
349
+ });
350
+ expect(exportFilesSpy).toHaveBeenCalled();
351
+ expect(saveMessagesSpy).not.toHaveBeenCalled();
352
+ });
353
+
354
+ test("uses saveMessages when exportFiles is not defined", async () => {
355
+ const saveMessagesSpy = vi.fn().mockResolvedValue([]);
356
+ const mockPlugin: InlangPlugin = {
357
+ key: "mock",
358
+ saveMessages: saveMessagesSpy,
359
+ };
360
+ const volume = Volume.fromJSON({});
361
+ const project = await loadProjectInMemory({
362
+ blob: await newProject(),
363
+ providePlugins: [mockPlugin],
364
+ });
365
+ await saveProjectToDirectory({
366
+ path: "/foo/project.inlang",
367
+ fs: volume.promises as any,
368
+ project,
369
+ });
370
+ expect(saveMessagesSpy).toHaveBeenCalled();
371
+ });
@@ -48,19 +48,6 @@ export async function saveProjectToDirectory(args: {
48
48
  const settings = await args.project.settings.get();
49
49
 
50
50
  for (const plugin of plugins) {
51
- // old legacy remove with v3
52
- if (plugin.saveMessages) {
53
- // in-efficient re-qeuery but it's a legacy function that will be removed.
54
- // the effort of adjusting the code to not re-query is not worth it.
55
- const bundlesNested = await selectBundleNested(args.project.db).execute();
56
- await plugin.saveMessages({
57
- messages: bundlesNested.map((b) => toMessageV1(b)),
58
- // @ts-expect-error - legacy
59
- nodeishFs: withAbsolutePaths(args.fs, args.path),
60
- settings,
61
- });
62
- }
63
-
64
51
  if (plugin.exportFiles) {
65
52
  const bundles = await args.project.db
66
53
  .selectFrom("bundle")
@@ -81,7 +68,10 @@ export async function saveProjectToDirectory(args: {
81
68
  settings,
82
69
  });
83
70
  for (const file of files) {
84
- const p = absolutePathFromProject(args.path, file.name);
71
+ const pathPattern = settings[plugin.key]?.pathPattern;
72
+ const p = pathPattern
73
+ ? pathPattern.replace(/\{(languageTag|locale)\}/g, file.locale)
74
+ : absolutePathFromProject(args.path, file.name);
85
75
  const dirname = path.dirname(p);
86
76
  if ((await args.fs.stat(dirname)).isDirectory() === false) {
87
77
  await args.fs.mkdir(dirname, { recursive: true });
@@ -106,5 +96,17 @@ export async function saveProjectToDirectory(args: {
106
96
  }
107
97
  }
108
98
  }
99
+ // old legacy remove with v3
100
+ else if (plugin.saveMessages) {
101
+ // in-efficient re-qeuery but it's a legacy function that will be removed.
102
+ // the effort of adjusting the code to not re-query is not worth it.
103
+ const bundlesNested = await selectBundleNested(args.project.db).execute();
104
+ await plugin.saveMessages({
105
+ messages: bundlesNested.map((b) => toMessageV1(b)),
106
+ // @ts-expect-error - legacy
107
+ nodeishFs: withAbsolutePaths(args.fs, args.path),
108
+ settings,
109
+ });
110
+ }
109
111
  }
110
112
  }