@inlang/paraglide-js 2.27.0 → 2.28.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (171) hide show
  1. package/README.md +9 -0
  2. package/dist/bundler-plugins/per-locale-build/index.js +14 -7
  3. package/dist/bundler-plugins/per-locale-build/index.js.map +1 -1
  4. package/dist/bundler-plugins/per-locale-build/vite-environments.test.js +235 -2
  5. package/dist/bundler-plugins/per-locale-build/vite-environments.test.js.map +1 -1
  6. package/dist/bundler-plugins/unplugin.d.ts +1 -1
  7. package/dist/bundler-plugins/unplugin.js +79 -10
  8. package/dist/bundler-plugins/unplugin.js.map +1 -1
  9. package/dist/bundler-plugins/unplugin.test.js +334 -1
  10. package/dist/bundler-plugins/unplugin.test.js.map +1 -1
  11. package/dist/bundler-plugins/vite.js +2 -1
  12. package/dist/bundler-plugins/vite.js.map +1 -1
  13. package/dist/bundler-plugins/vite.test.js +1 -1
  14. package/dist/bundler-plugins/vite.test.js.map +1 -1
  15. package/dist/cli/commands/compile/command.js +13 -0
  16. package/dist/cli/commands/compile/command.js.map +1 -1
  17. package/dist/cli/commands/compile/command.test.js +87 -3
  18. package/dist/cli/commands/compile/command.test.js.map +1 -1
  19. package/dist/cli/commands/init/command.d.ts +5 -0
  20. package/dist/cli/commands/init/command.js +213 -59
  21. package/dist/cli/commands/init/command.js.map +1 -1
  22. package/dist/cli/commands/init/command.test.d.ts +1 -0
  23. package/dist/cli/commands/init/command.test.js +123 -0
  24. package/dist/cli/commands/init/command.test.js.map +1 -0
  25. package/dist/cli/init-options.d.ts +11 -0
  26. package/dist/cli/init-options.js +2 -0
  27. package/dist/cli/init-options.js.map +1 -0
  28. package/dist/cli/steps/add-inlang-check.js +2 -2
  29. package/dist/cli/steps/add-inlang-check.js.map +1 -1
  30. package/dist/cli/steps/add-message-lint.d.ts +34 -0
  31. package/dist/cli/steps/add-message-lint.js +105 -0
  32. package/dist/cli/steps/add-message-lint.js.map +1 -0
  33. package/dist/cli/steps/add-message-lint.test.d.ts +1 -0
  34. package/dist/cli/steps/add-message-lint.test.js +74 -0
  35. package/dist/cli/steps/add-message-lint.test.js.map +1 -0
  36. package/dist/cli/steps/add-vite-plugin.d.ts +18 -0
  37. package/dist/cli/steps/add-vite-plugin.js +34 -6
  38. package/dist/cli/steps/add-vite-plugin.js.map +1 -1
  39. package/dist/cli/steps/add-vite-plugin.test.js +25 -9
  40. package/dist/cli/steps/add-vite-plugin.test.js.map +1 -1
  41. package/dist/cli/steps/check-for-uncomitted-changes.d.ts +3 -0
  42. package/dist/cli/steps/check-for-uncomitted-changes.js +15 -3
  43. package/dist/cli/steps/check-for-uncomitted-changes.js.map +1 -1
  44. package/dist/cli/steps/detect-bundler.d.ts +1 -0
  45. package/dist/cli/steps/detect-bundler.js +7 -1
  46. package/dist/cli/steps/detect-bundler.js.map +1 -1
  47. package/dist/cli/steps/initialize-inlang-project.d.ts +4 -3
  48. package/dist/cli/steps/initialize-inlang-project.js +60 -157
  49. package/dist/cli/steps/initialize-inlang-project.js.map +1 -1
  50. package/dist/cli/steps/maybe-add-machine-translation.d.ts +4 -0
  51. package/dist/cli/steps/maybe-add-machine-translation.js +11 -6
  52. package/dist/cli/steps/maybe-add-machine-translation.js.map +1 -1
  53. package/dist/cli/steps/maybe-add-sherlock.d.ts +2 -0
  54. package/dist/cli/steps/maybe-add-sherlock.js +12 -6
  55. package/dist/cli/steps/maybe-add-sherlock.js.map +1 -1
  56. package/dist/cli/steps/maybe-add-sherlock.test.d.ts +1 -0
  57. package/dist/cli/steps/maybe-add-sherlock.test.js +44 -0
  58. package/dist/cli/steps/maybe-add-sherlock.test.js.map +1 -0
  59. package/dist/cli/steps/prompt-for-outdir.d.ts +2 -0
  60. package/dist/cli/steps/prompt-for-outdir.js +4 -0
  61. package/dist/cli/steps/prompt-for-outdir.js.map +1 -1
  62. package/dist/cli/steps/update-package-json.js +8 -13
  63. package/dist/cli/steps/update-package-json.js.map +1 -1
  64. package/dist/cli/steps/update-ts-config.d.ts +6 -0
  65. package/dist/cli/steps/update-ts-config.js +27 -4
  66. package/dist/cli/steps/update-ts-config.js.map +1 -1
  67. package/dist/cli/utils.d.ts +2 -0
  68. package/dist/cli/utils.js +6 -0
  69. package/dist/cli/utils.js.map +1 -1
  70. package/dist/cli/utils.test.d.ts +1 -0
  71. package/dist/cli/utils.test.js +16 -0
  72. package/dist/cli/utils.test.js.map +1 -0
  73. package/dist/compiler/compile-annotation.js +6 -1
  74. package/dist/compiler/compile-annotation.js.map +1 -1
  75. package/dist/compiler/compile-bundle.d.ts +4 -0
  76. package/dist/compiler/compile-bundle.js +67 -2
  77. package/dist/compiler/compile-bundle.js.map +1 -1
  78. package/dist/compiler/compile-bundle.test.js +214 -1
  79. package/dist/compiler/compile-bundle.test.js.map +1 -1
  80. package/dist/compiler/compile-lifecycle.test.d.ts +1 -0
  81. package/dist/compiler/compile-lifecycle.test.js +69 -0
  82. package/dist/compiler/compile-lifecycle.test.js.map +1 -0
  83. package/dist/compiler/compile-local-variable.test.js +14 -14
  84. package/dist/compiler/compile-local-variable.test.js.map +1 -1
  85. package/dist/compiler/compile-message.exact-number.test.js +1 -1
  86. package/dist/compiler/compile-message.exact-number.test.js.map +1 -1
  87. package/dist/compiler/compile-message.locals.test.js +1 -1
  88. package/dist/compiler/compile-message.locals.test.js.map +1 -1
  89. package/dist/compiler/compile-message.test.js +2 -2
  90. package/dist/compiler/compile-message.test.js.map +1 -1
  91. package/dist/compiler/compile-pattern.test.js +5 -5
  92. package/dist/compiler/compile-pattern.test.js.map +1 -1
  93. package/dist/compiler/compile-project.js +1 -0
  94. package/dist/compiler/compile-project.js.map +1 -1
  95. package/dist/compiler/compile-project.test.js +94 -1
  96. package/dist/compiler/compile-project.test.js.map +1 -1
  97. package/dist/compiler/compile.js +36 -17
  98. package/dist/compiler/compile.js.map +1 -1
  99. package/dist/compiler/compile.test.js +70 -0
  100. package/dist/compiler/compile.test.js.map +1 -1
  101. package/dist/compiler/compiler-options.d.ts +41 -0
  102. package/dist/compiler/compiler-options.js.map +1 -1
  103. package/dist/compiler/output-structure/message-modules.js +1 -1
  104. package/dist/compiler/output-structure/message-modules.js.map +1 -1
  105. package/dist/compiler/registry.js +71 -13
  106. package/dist/compiler/registry.js.map +1 -1
  107. package/dist/compiler/registry.test.d.ts +1 -0
  108. package/dist/compiler/registry.test.js +291 -0
  109. package/dist/compiler/registry.test.js.map +1 -0
  110. package/dist/compiler/runtime/create-runtime.d.ts +2 -0
  111. package/dist/compiler/runtime/create-runtime.js +9 -0
  112. package/dist/compiler/runtime/create-runtime.js.map +1 -1
  113. package/dist/compiler/runtime/extract-locale-from-cookie.js +8 -1
  114. package/dist/compiler/runtime/extract-locale-from-cookie.js.map +1 -1
  115. package/dist/compiler/runtime/extract-locale-from-cookie.test.js +26 -0
  116. package/dist/compiler/runtime/extract-locale-from-cookie.test.js.map +1 -1
  117. package/dist/compiler/runtime/extract-locale-from-header.js +47 -5
  118. package/dist/compiler/runtime/extract-locale-from-header.js.map +1 -1
  119. package/dist/compiler/runtime/extract-locale-from-header.test.js +58 -0
  120. package/dist/compiler/runtime/extract-locale-from-header.test.js.map +1 -1
  121. package/dist/compiler/runtime/get-locale.js +7 -1
  122. package/dist/compiler/runtime/get-locale.js.map +1 -1
  123. package/dist/compiler/runtime/get-locale.test.js +95 -0
  124. package/dist/compiler/runtime/get-locale.test.js.map +1 -1
  125. package/dist/compiler/runtime/localize-href.d.ts +8 -0
  126. package/dist/compiler/runtime/localize-href.js +60 -0
  127. package/dist/compiler/runtime/localize-href.js.map +1 -1
  128. package/dist/compiler/runtime/localize-href.test.js +227 -1
  129. package/dist/compiler/runtime/localize-href.test.js.map +1 -1
  130. package/dist/compiler/runtime/set-locale.js +24 -6
  131. package/dist/compiler/runtime/set-locale.js.map +1 -1
  132. package/dist/compiler/runtime/set-locale.test.js +182 -0
  133. package/dist/compiler/runtime/set-locale.test.js.map +1 -1
  134. package/dist/compiler/runtime/type.d.ts +2 -0
  135. package/dist/compiler/runtime/type.js.map +1 -1
  136. package/dist/compiler/runtime/type.test.js +34 -0
  137. package/dist/compiler/runtime/type.test.js.map +1 -1
  138. package/dist/compiler/runtime/variables.d.ts +2 -0
  139. package/dist/compiler/runtime/variables.js +7 -0
  140. package/dist/compiler/runtime/variables.js.map +1 -1
  141. package/dist/compiler/server/middleware.d.ts +8 -2
  142. package/dist/compiler/server/middleware.js +175 -7
  143. package/dist/compiler/server/middleware.js.map +1 -1
  144. package/dist/compiler/server/middleware.test.js +750 -3
  145. package/dist/compiler/server/middleware.test.js.map +1 -1
  146. package/dist/eslint/index.d.ts +4 -0
  147. package/dist/eslint/index.js +8 -0
  148. package/dist/eslint/index.js.map +1 -0
  149. package/dist/eslint/no-dynamic-message-access.d.ts +3 -0
  150. package/dist/eslint/no-dynamic-message-access.js +150 -0
  151. package/dist/eslint/no-dynamic-message-access.js.map +1 -0
  152. package/dist/eslint/no-dynamic-message-access.test.d.ts +1 -0
  153. package/dist/eslint/no-dynamic-message-access.test.js +126 -0
  154. package/dist/eslint/no-dynamic-message-access.test.js.map +1 -0
  155. package/dist/eslint/oxlint.test.d.ts +1 -0
  156. package/dist/eslint/oxlint.test.js +64 -0
  157. package/dist/eslint/oxlint.test.js.map +1 -0
  158. package/dist/services/config/config-schema.d.ts +2 -0
  159. package/dist/services/config/config-schema.js +2 -0
  160. package/dist/services/config/config-schema.js.map +1 -1
  161. package/dist/services/config/load-paraglide-config.test.js +12 -0
  162. package/dist/services/config/load-paraglide-config.test.js.map +1 -1
  163. package/dist/services/env-variables/index.js +1 -1
  164. package/dist/services/env-variables/index.js.map +1 -1
  165. package/dist/services/file-handling/write-output.bench.js +51 -11
  166. package/dist/services/file-handling/write-output.bench.js.map +1 -1
  167. package/dist/services/file-handling/write-output.js +60 -20
  168. package/dist/services/file-handling/write-output.js.map +1 -1
  169. package/dist/services/file-handling/write-output.test.js +175 -0
  170. package/dist/services/file-handling/write-output.test.js.map +1 -1
  171. package/package.json +14 -4
@@ -2,174 +2,77 @@ import { loadProjectFromDirectory, loadProjectInMemory, newProject, saveProjectT
2
2
  import { getNewProjectTemplate } from "../defaults.js";
3
3
  import { DEFAULT_PROJECT_PATH } from "../../services/config/defaults.js";
4
4
  import nodePath from "node:path";
5
- import fs from "node:fs";
6
5
  export const initializeInlangProject = async (ctx) => {
7
- // const existingProjectPaths =
8
- // // checking for undefined if node version is lower than 22
9
- // typeof fs.globSync !== "undefined" ? fs.globSync("*.inlang") : [];
10
- // if (existingProjectPaths.length > 0) {
11
- // const { project, projectPath } = await existingProjectFlow({
12
- // existingProjectPaths,
13
- // fs: ctx.fs,
14
- // syncFs: fs,
15
- // logger: ctx.logger,
16
- // });
17
- // return {
18
- // ...ctx,
19
- // project,
20
- // projectPath,
21
- // };
22
- // } else {
23
- const { project, projectPath } = await createNewProjectFlow(ctx);
24
- return {
25
- ...ctx,
26
- project,
27
- projectPath,
28
- };
29
- // }
6
+ const projectPath = nodePath.resolve(ctx.root, ctx.projectPath ?? DEFAULT_PROJECT_PATH);
7
+ const existing = await ctx.fs
8
+ .access(nodePath.join(projectPath, "settings.json"))
9
+ .then(() => true, () => false);
10
+ if (!existing)
11
+ return { ...ctx, ...(await createNewProjectFlow({ ...ctx, projectPath })) };
12
+ const project = await loadProjectFromDirectory({
13
+ path: projectPath,
14
+ fs: ctx.syncFs,
15
+ });
16
+ const errors = await project.errors.get();
17
+ if (errors.length) {
18
+ await project.close();
19
+ throw new AggregateError(errors, "Existing inlang project has errors.");
20
+ }
21
+ ctx.logger.success("Using the existing inlang project.");
22
+ return { ...ctx, project, projectPath };
30
23
  };
31
- // export const existingProjectFlow = async (ctx: {
32
- // /** An array of absolute paths to existing projects. */
33
- // existingProjectPaths: string[];
34
- // fs: typeof fs.promises;
35
- // syncFs: typeof fs;
36
- // logger: Logger;
37
- // }): Promise<{ project: InlangProject; projectPath: string }> => {
38
- // const NEW_PROJECT_VALUE = "newProject";
39
- // const commonPrefix = getCommonPrefix(ctx.existingProjectPaths);
40
- // const options = ctx.existingProjectPaths.map((path) => {
41
- // return {
42
- // label: path.replace(commonPrefix, ""),
43
- // value: path,
44
- // };
45
- // });
46
- // const selection = (await prompt(
47
- // `Do you want to use an existing Inlang Project or create a new one?`,
48
- // {
49
- // type: "select",
50
- // options: [
51
- // { label: "Create a new project", value: NEW_PROJECT_VALUE },
52
- // ...options,
53
- // ],
54
- // }
55
- // )) as unknown as string; // the prompt type is incorrect
56
- // //if the user wants to create a new project - create one & use it
57
- // if (selection === NEW_PROJECT_VALUE) return createNewProjectFlow(ctx);
58
- // const projectPath = selection;
59
- // const project = await loadProjectFromDirectory({
60
- // path: projectPath,
61
- // fs: ctx.syncFs,
62
- // });
63
- // if ((await project.errors.get()).length > 0) {
64
- // ctx.logger.error(
65
- // "Aborting paragilde initialization. - The selected project has errors. Either fix them, or remove the project and create a new one."
66
- // );
67
- // for (const error of await project.errors.get()) {
68
- // ctx.logger.error(error);
69
- // }
70
- // process.exit(1);
71
- // }
72
- // return { project, projectPath };
73
- // };
74
- // function parseLocaleInput(input: string): {
75
- // validlocales: string[];
76
- // invalidlocales: string[];
77
- // } {
78
- // const locales = input
79
- // .replaceAll(/[,:\s]/g, " ") //replace common separators with spaces
80
- // .split(" ")
81
- // .filter(Boolean) //remove empty segments
82
- // .map((tag) => tag.toLowerCase());
83
- // const validlocales: string[] = [];
84
- // const invalidlocales: string[] = [];
85
- // for (const tag of locales) {
86
- // if (isValidlocale(tag)) {
87
- // validlocales.push(tag);
88
- // } else {
89
- // invalidlocales.push(tag);
90
- // }
91
- // }
92
- // return {
93
- // validlocales,
94
- // invalidlocales,
95
- // };
96
- // }
97
- // async function promptForLocales(
98
- // initialLocales: string[] = []
99
- // ): Promise<string[]> {
100
- // const localesInput =
101
- // (await prompt("Which locales do you want to support?", {
102
- // type: "text",
103
- // placeholder: "en, de-ch, ar",
104
- // initial: initialLocales.length ? initialLocales.join(", ") : undefined,
105
- // })) ?? "";
106
- // const { invalidlocales: invalidLocales, validlocales } =
107
- // parseLocaleInput(localesInput);
108
- // if (validlocales.length === 0) {
109
- // consola.warn("You must specify at least one locale");
110
- // return await promptForLocales();
111
- // }
112
- // if (invalidLocales.length > 0) {
113
- // const message =
114
- // invalidLocales.length === 1
115
- // ? invalidLocales[0] +
116
- // " isn't a valid locale. Please stick to IEEE BCP-47 Language Tags"
117
- // : invalidLocales.map((tag) => `"${tag}"`).join(", ") +
118
- // " aren't valid locales. Please stick to IEEE BCP-47 Language Tags";
119
- // consola.warn(message);
120
- // return await promptForLocales(validlocales);
121
- // }
122
- // return validlocales;
123
- // }
124
24
  export const createNewProjectFlow = async (ctx) => {
25
+ const root = ctx.root ?? process.cwd();
26
+ const projectPath = nodePath.resolve(root, ctx.projectPath ?? DEFAULT_PROJECT_PATH);
125
27
  const settings = getNewProjectTemplate();
126
- const messagePath = settings["plugin.inlang.messageFormat"].pathPattern;
127
- //create the messages dir if it doesn't exist
128
- const messageDir = nodePath.dirname(nodePath.resolve(process.cwd(), messagePath));
129
- await ctx.fs.mkdir(messageDir, { recursive: true });
130
- await Promise.allSettled(settings.locales.map(async (locale) => {
131
- const languageFile = nodePath.resolve(messageDir, locale + ".json");
132
- const exists = await ctx.fs
133
- .access(languageFile)
134
- .then(() => true)
135
- .catch(() => false);
136
- if (exists)
137
- return;
138
- await ctx.fs.writeFile(languageFile, JSON.stringify({
139
- $schema: "https://inlang.com/schema/inlang-message-format",
140
- // add an example message for instant aha moment
141
- example_message: locale === "en"
142
- ? "Hello world {username}"
143
- : "Guten Tag {username}",
144
- }, null, 2));
28
+ // The SDK resolves message paths from the parent of the .inlang directory.
29
+ const relativeMessages = nodePath
30
+ .relative(nodePath.dirname(projectPath), nodePath.join(root, "messages", "{locale}.json"))
31
+ .split(nodePath.sep)
32
+ .join("/");
33
+ settings["plugin.inlang.messageFormat"].pathPattern =
34
+ relativeMessages.startsWith(".")
35
+ ? relativeMessages
36
+ : "./" + relativeMessages;
37
+ await ctx.fs.mkdir(nodePath.join(root, "messages"), { recursive: true });
38
+ await Promise.all(settings.locales.map(async (locale) => {
39
+ const file = nodePath.join(root, "messages", locale + ".json");
40
+ try {
41
+ await ctx.fs.writeFile(file, JSON.stringify({
42
+ $schema: "https://inlang.com/schema/inlang-message-format",
43
+ example_message: locale === "en"
44
+ ? "Hello world {username}"
45
+ : "Guten Tag {username}",
46
+ }, null, 2), { flag: "wx" });
47
+ }
48
+ catch (error) {
49
+ if (error.code !== "EEXIST")
50
+ throw error;
51
+ }
145
52
  }));
146
- const projectPath = DEFAULT_PROJECT_PATH;
147
- //create default project
148
- await ctx.fs.mkdir(projectPath, { recursive: true });
149
- const tempProject = await loadProjectInMemory({
150
- blob: await newProject({
151
- settings,
152
- }),
153
- });
154
- await saveProjectToDirectory({
155
- project: tempProject,
156
- fs: ctx.fs,
157
- path: projectPath,
53
+ const temporary = await loadProjectInMemory({
54
+ blob: await newProject({ settings }),
158
55
  });
56
+ try {
57
+ await saveProjectToDirectory({
58
+ project: temporary,
59
+ fs: ctx.fs,
60
+ path: projectPath,
61
+ });
62
+ }
63
+ finally {
64
+ await temporary.close();
65
+ }
159
66
  const project = await loadProjectFromDirectory({
160
67
  path: projectPath,
161
68
  fs: ctx.syncFs,
162
69
  });
163
- if ((await project.errors.get()).length > 0) {
164
- ctx.logger.error("Failed to create a new inlang project.\n\nThis is likely an internal bug. Please file an issue at https://github.com/opral/inlang-paraglide-js.");
165
- for (const error of await project.errors.get()) {
166
- ctx.logger.error(error);
167
- }
168
- return process.exit(1);
169
- }
170
- else {
171
- ctx.logger.success("Created a new inlang project.");
70
+ const errors = await project.errors.get();
71
+ if (errors.length) {
72
+ await project.close();
73
+ throw new AggregateError(errors, "Failed to create the inlang project.");
172
74
  }
75
+ ctx.logger.success("Created a new inlang project.");
173
76
  return { project, projectPath };
174
77
  };
175
78
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"initialize-inlang-project.js","sourceRoot":"","sources":["../../../src/cli/steps/initialize-inlang-project.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n\tloadProjectFromDirectory,\n\tloadProjectInMemory,\n\tnewProject,\n\tsaveProjectToDirectory,\n\ttype InlangProject,\n} from \"@inlang/sdk\";\nimport type { Logger } from \"../../services/logger/index.js\";\nimport type { CliStep } from \"../utils.js\";\nimport { getNewProjectTemplate } from \"../defaults.js\";\nimport { DEFAULT_PROJECT_PATH } from \"../../services/config/defaults.js\";\nimport nodePath from \"node:path\";\nimport fs from \"node:fs\";\n\nexport const initializeInlangProject: CliStep<\n\t{\n\t\tfs: typeof fs.promises;\n\t\tsyncFs: typeof fs;\n\t\tlogger: Logger;\n\t\troot: string;\n\t},\n\t{\n\t\tproject: InlangProject;\n\t\t/** Relative path to the project */\n\t\tprojectPath: string;\n\t}\n> = async (ctx) => {\n\t// const existingProjectPaths =\n\t// \t// checking for undefined if node version is lower than 22\n\t// \ttypeof fs.globSync !== \"undefined\" ? fs.globSync(\"*.inlang\") : [];\n\n\t// if (existingProjectPaths.length > 0) {\n\t// \tconst { project, projectPath } = await existingProjectFlow({\n\t// \t\texistingProjectPaths,\n\t// \t\tfs: ctx.fs,\n\t// \t\tsyncFs: fs,\n\t// \t\tlogger: ctx.logger,\n\t// \t});\n\n\t// \treturn {\n\t// \t\t...ctx,\n\t// \t\tproject,\n\t// \t\tprojectPath,\n\t// \t};\n\t// } else {\n\tconst { project, projectPath } = await createNewProjectFlow(ctx);\n\treturn {\n\t\t...ctx,\n\t\tproject,\n\t\tprojectPath,\n\t};\n\t// }\n};\n\n// export const existingProjectFlow = async (ctx: {\n// \t/** An array of absolute paths to existing projects. */\n// \texistingProjectPaths: string[];\n// \tfs: typeof fs.promises;\n// \tsyncFs: typeof fs;\n// \tlogger: Logger;\n// }): Promise<{ project: InlangProject; projectPath: string }> => {\n// \tconst NEW_PROJECT_VALUE = \"newProject\";\n\n// \tconst commonPrefix = getCommonPrefix(ctx.existingProjectPaths);\n// \tconst options = ctx.existingProjectPaths.map((path) => {\n// \t\treturn {\n// \t\t\tlabel: path.replace(commonPrefix, \"\"),\n// \t\t\tvalue: path,\n// \t\t};\n// \t});\n\n// \tconst selection = (await prompt(\n// \t\t`Do you want to use an existing Inlang Project or create a new one?`,\n// \t\t{\n// \t\t\ttype: \"select\",\n// \t\t\toptions: [\n// \t\t\t\t{ label: \"Create a new project\", value: NEW_PROJECT_VALUE },\n// \t\t\t\t...options,\n// \t\t\t],\n// \t\t}\n// \t)) as unknown as string; // the prompt type is incorrect\n\n// \t//if the user wants to create a new project - create one & use it\n// \tif (selection === NEW_PROJECT_VALUE) return createNewProjectFlow(ctx);\n\n// \tconst projectPath = selection;\n// \tconst project = await loadProjectFromDirectory({\n// \t\tpath: projectPath,\n// \t\tfs: ctx.syncFs,\n// \t});\n\n// \tif ((await project.errors.get()).length > 0) {\n// \t\tctx.logger.error(\n// \t\t\t\"Aborting paragilde initialization. - The selected project has errors. Either fix them, or remove the project and create a new one.\"\n// \t\t);\n// \t\tfor (const error of await project.errors.get()) {\n// \t\t\tctx.logger.error(error);\n// \t\t}\n// \t\tprocess.exit(1);\n// \t}\n\n// \treturn { project, projectPath };\n// };\n\n// function parseLocaleInput(input: string): {\n// \tvalidlocales: string[];\n// \tinvalidlocales: string[];\n// } {\n// \tconst locales = input\n// \t\t.replaceAll(/[,:\\s]/g, \" \") //replace common separators with spaces\n// \t\t.split(\" \")\n// \t\t.filter(Boolean) //remove empty segments\n// \t\t.map((tag) => tag.toLowerCase());\n\n// \tconst validlocales: string[] = [];\n// \tconst invalidlocales: string[] = [];\n\n// \tfor (const tag of locales) {\n// \t\tif (isValidlocale(tag)) {\n// \t\t\tvalidlocales.push(tag);\n// \t\t} else {\n// \t\t\tinvalidlocales.push(tag);\n// \t\t}\n// \t}\n\n// \treturn {\n// \t\tvalidlocales,\n// \t\tinvalidlocales,\n// \t};\n// }\n\n// async function promptForLocales(\n// \tinitialLocales: string[] = []\n// ): Promise<string[]> {\n// \tconst localesInput =\n// \t\t(await prompt(\"Which locales do you want to support?\", {\n// \t\t\ttype: \"text\",\n// \t\t\tplaceholder: \"en, de-ch, ar\",\n// \t\t\tinitial: initialLocales.length ? initialLocales.join(\", \") : undefined,\n// \t\t})) ?? \"\";\n\n// \tconst { invalidlocales: invalidLocales, validlocales } =\n// \t\tparseLocaleInput(localesInput);\n\n// \tif (validlocales.length === 0) {\n// \t\tconsola.warn(\"You must specify at least one locale\");\n// \t\treturn await promptForLocales();\n// \t}\n\n// \tif (invalidLocales.length > 0) {\n// \t\tconst message =\n// \t\t\tinvalidLocales.length === 1\n// \t\t\t\t? invalidLocales[0] +\n// \t\t\t\t\t\" isn't a valid locale. Please stick to IEEE BCP-47 Language Tags\"\n// \t\t\t\t: invalidLocales.map((tag) => `\"${tag}\"`).join(\", \") +\n// \t\t\t\t\t\" aren't valid locales. Please stick to IEEE BCP-47 Language Tags\";\n\n// \t\tconsola.warn(message);\n// \t\treturn await promptForLocales(validlocales);\n// \t}\n\n// \treturn validlocales;\n// }\nexport const createNewProjectFlow = async (ctx: {\n\tfs: typeof fs.promises;\n\tsyncFs: typeof fs;\n\tlogger: Logger;\n}): Promise<{\n\tproject: InlangProject;\n\t/** An absolute path to the created project */\n\tprojectPath: string;\n}> => {\n\tconst settings = getNewProjectTemplate();\n\n\tconst messagePath = settings[\"plugin.inlang.messageFormat\"].pathPattern;\n\n\t//create the messages dir if it doesn't exist\n\tconst messageDir = nodePath.dirname(\n\t\tnodePath.resolve(process.cwd(), messagePath)\n\t);\n\tawait ctx.fs.mkdir(messageDir, { recursive: true });\n\n\tawait Promise.allSettled(\n\t\tsettings.locales.map(async (locale) => {\n\t\t\tconst languageFile = nodePath.resolve(messageDir, locale + \".json\");\n\t\t\tconst exists = await ctx.fs\n\t\t\t\t.access(languageFile)\n\t\t\t\t.then(() => true)\n\t\t\t\t.catch(() => false);\n\t\t\tif (exists) return;\n\t\t\tawait ctx.fs.writeFile(\n\t\t\t\tlanguageFile,\n\t\t\t\tJSON.stringify(\n\t\t\t\t\t{\n\t\t\t\t\t\t$schema: \"https://inlang.com/schema/inlang-message-format\",\n\t\t\t\t\t\t// add an example message for instant aha moment\n\t\t\t\t\t\texample_message:\n\t\t\t\t\t\t\tlocale === \"en\"\n\t\t\t\t\t\t\t\t? \"Hello world {username}\"\n\t\t\t\t\t\t\t\t: \"Guten Tag {username}\",\n\t\t\t\t\t},\n\t\t\t\t\tnull,\n\t\t\t\t\t2\n\t\t\t\t)\n\t\t\t);\n\t\t})\n\t);\n\n\tconst projectPath = DEFAULT_PROJECT_PATH;\n\n\t//create default project\n\tawait ctx.fs.mkdir(projectPath, { recursive: true });\n\n\tconst tempProject = await loadProjectInMemory({\n\t\tblob: await newProject({\n\t\t\tsettings,\n\t\t}),\n\t});\n\n\tawait saveProjectToDirectory({\n\t\tproject: tempProject,\n\t\tfs: ctx.fs,\n\t\tpath: projectPath,\n\t});\n\n\tconst project = await loadProjectFromDirectory({\n\t\tpath: projectPath,\n\t\tfs: ctx.syncFs,\n\t});\n\n\tif ((await project.errors.get()).length > 0) {\n\t\tctx.logger.error(\n\t\t\t\"Failed to create a new inlang project.\\n\\nThis is likely an internal bug. Please file an issue at https://github.com/opral/inlang-paraglide-js.\"\n\t\t);\n\t\tfor (const error of await project.errors.get()) {\n\t\t\tctx.logger.error(error);\n\t\t}\n\t\treturn process.exit(1);\n\t} else {\n\t\tctx.logger.success(\"Created a new inlang project.\");\n\t}\n\treturn { project, projectPath };\n};\n\n/**\n * Get's the common prefix of a set of strings.\n * If only one string is passed the prefix will be the empty string\n *\n * @example\n * ```ts\n * getCommonPrefix([\"foo\", \"foobar\"]) // \"foo\"\n * getCommonPrefix([\"foobar\"]) // \"\"\n * ```\n */\nexport function getCommonPrefix(strings: string[]): string {\n\tconst strs = strings.filter(Boolean);\n\tif (strs.length <= 1) return \"\";\n\n\tconst firstString = strs[0];\n\tif (firstString === undefined) {\n\t\treturn \"\";\n\t}\n\n\treturn strs.reduce(\n\t\t(commonPrefix, str) => longestCommonPrefix(commonPrefix, str),\n\t\tfirstString\n\t);\n}\n\nfunction longestCommonPrefix(strA: string, strB: string): string {\n\tlet commonPrefix = \"\";\n\tfor (let i = 0; i < Math.min(strA.length, strB.length); i++) {\n\t\tif (strA[i] === strB[i]) {\n\t\t\tcommonPrefix += strA[i];\n\t\t} else {\n\t\t\tbreak;\n\t\t}\n\t}\n\treturn commonPrefix;\n}\n\n/**\n * Follows the IETF BCP 47 locale schema with modifications.\n */\nexport const pattern =\n\t\"^((?<grandfathered>(en-GB-oed|i-ami|i-bnn|i-default|i-enochian|i-hak|i-klingon|i-lux|i-mingo|i-navajo|i-pwn|i-tao|i-tay|i-tsu|sgn-BE-FR|sgn-BE-NL|sgn-CH-DE)|(art-lojban|cel-gaulish|no-bok|no-nyn|zh-guoyu|zh-hakka|zh-min|zh-min-nan|zh-xiang))|((?<language>([A-Za-z]{2,3}(-(?<extlang>[A-Za-z]{3}(-[A-Za-z]{3}){0,2}))?))(-(?<script>[A-Za-z]{4}))?(-(?<region>[A-Za-z]{2}|[0-9]{3}))?(-(?<variant>[A-Za-z0-9]{5,8}|[0-9][A-Za-z0-9]{3}))*))$\";\n\n// const isValidlocale = (locale: string): boolean =>\n// \tRegExp(`${pattern}`).test(locale);\n"]}
1
+ {"version":3,"file":"initialize-inlang-project.js","sourceRoot":"","sources":["../../../src/cli/steps/initialize-inlang-project.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n\tloadProjectFromDirectory,\n\tloadProjectInMemory,\n\tnewProject,\n\tsaveProjectToDirectory,\n\ttype InlangProject,\n} from \"@inlang/sdk\";\nimport type { Logger } from \"../../services/logger/index.js\";\nimport type { CliStep } from \"../utils.js\";\nimport { getNewProjectTemplate } from \"../defaults.js\";\nimport { DEFAULT_PROJECT_PATH } from \"../../services/config/defaults.js\";\nimport nodePath from \"node:path\";\nimport type fs from \"node:fs\";\n\nexport const initializeInlangProject: CliStep<\n\t{\n\t\tfs: typeof fs.promises;\n\t\tsyncFs: typeof fs;\n\t\tlogger: Logger;\n\t\troot: string;\n\t\tprojectPath?: string;\n\t},\n\t{ project: InlangProject; projectPath: string }\n> = async (ctx) => {\n\tconst projectPath = nodePath.resolve(\n\t\tctx.root,\n\t\tctx.projectPath ?? DEFAULT_PROJECT_PATH\n\t);\n\tconst existing = await ctx.fs\n\t\t.access(nodePath.join(projectPath, \"settings.json\"))\n\t\t.then(\n\t\t\t() => true,\n\t\t\t() => false\n\t\t);\n\tif (!existing)\n\t\treturn { ...ctx, ...(await createNewProjectFlow({ ...ctx, projectPath })) };\n\tconst project = await loadProjectFromDirectory({\n\t\tpath: projectPath,\n\t\tfs: ctx.syncFs,\n\t});\n\tconst errors = await project.errors.get();\n\tif (errors.length) {\n\t\tawait project.close();\n\t\tthrow new AggregateError(errors, \"Existing inlang project has errors.\");\n\t}\n\tctx.logger.success(\"Using the existing inlang project.\");\n\treturn { ...ctx, project, projectPath };\n};\n\nexport const createNewProjectFlow = async (ctx: {\n\tfs: typeof fs.promises;\n\tsyncFs: typeof fs;\n\tlogger: Logger;\n\troot?: string;\n\tprojectPath?: string;\n}): Promise<{ project: InlangProject; projectPath: string }> => {\n\tconst root = ctx.root ?? process.cwd();\n\tconst projectPath = nodePath.resolve(\n\t\troot,\n\t\tctx.projectPath ?? DEFAULT_PROJECT_PATH\n\t);\n\tconst settings = getNewProjectTemplate();\n\t// The SDK resolves message paths from the parent of the .inlang directory.\n\tconst relativeMessages = nodePath\n\t\t.relative(\n\t\t\tnodePath.dirname(projectPath),\n\t\t\tnodePath.join(root, \"messages\", \"{locale}.json\")\n\t\t)\n\t\t.split(nodePath.sep)\n\t\t.join(\"/\");\n\tsettings[\"plugin.inlang.messageFormat\"].pathPattern =\n\t\trelativeMessages.startsWith(\".\")\n\t\t\t? relativeMessages\n\t\t\t: \"./\" + relativeMessages;\n\tawait ctx.fs.mkdir(nodePath.join(root, \"messages\"), { recursive: true });\n\tawait Promise.all(\n\t\tsettings.locales.map(async (locale) => {\n\t\t\tconst file = nodePath.join(root, \"messages\", locale + \".json\");\n\t\t\ttry {\n\t\t\t\tawait ctx.fs.writeFile(\n\t\t\t\t\tfile,\n\t\t\t\t\tJSON.stringify(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$schema: \"https://inlang.com/schema/inlang-message-format\",\n\t\t\t\t\t\t\texample_message:\n\t\t\t\t\t\t\t\tlocale === \"en\"\n\t\t\t\t\t\t\t\t\t? \"Hello world {username}\"\n\t\t\t\t\t\t\t\t\t: \"Guten Tag {username}\",\n\t\t\t\t\t\t},\n\t\t\t\t\t\tnull,\n\t\t\t\t\t\t2\n\t\t\t\t\t),\n\t\t\t\t\t{ flag: \"wx\" }\n\t\t\t\t);\n\t\t\t} catch (error) {\n\t\t\t\tif ((error as NodeJS.ErrnoException).code !== \"EEXIST\") throw error;\n\t\t\t}\n\t\t})\n\t);\n\tconst temporary = await loadProjectInMemory({\n\t\tblob: await newProject({ settings }),\n\t});\n\ttry {\n\t\tawait saveProjectToDirectory({\n\t\t\tproject: temporary,\n\t\t\tfs: ctx.fs,\n\t\t\tpath: projectPath,\n\t\t});\n\t} finally {\n\t\tawait temporary.close();\n\t}\n\tconst project = await loadProjectFromDirectory({\n\t\tpath: projectPath,\n\t\tfs: ctx.syncFs,\n\t});\n\tconst errors = await project.errors.get();\n\tif (errors.length) {\n\t\tawait project.close();\n\t\tthrow new AggregateError(errors, \"Failed to create the inlang project.\");\n\t}\n\tctx.logger.success(\"Created a new inlang project.\");\n\treturn { project, projectPath };\n};\n\n/**\n * Get's the common prefix of a set of strings.\n * If only one string is passed the prefix will be the empty string\n *\n * @example\n * ```ts\n * getCommonPrefix([\"foo\", \"foobar\"]) // \"foo\"\n * getCommonPrefix([\"foobar\"]) // \"\"\n * ```\n */\nexport function getCommonPrefix(strings: string[]): string {\n\tconst strs = strings.filter(Boolean);\n\tif (strs.length <= 1) return \"\";\n\n\tconst firstString = strs[0];\n\tif (firstString === undefined) {\n\t\treturn \"\";\n\t}\n\n\treturn strs.reduce(\n\t\t(commonPrefix, str) => longestCommonPrefix(commonPrefix, str),\n\t\tfirstString\n\t);\n}\n\nfunction longestCommonPrefix(strA: string, strB: string): string {\n\tlet commonPrefix = \"\";\n\tfor (let i = 0; i < Math.min(strA.length, strB.length); i++) {\n\t\tif (strA[i] === strB[i]) {\n\t\t\tcommonPrefix += strA[i];\n\t\t} else {\n\t\t\tbreak;\n\t\t}\n\t}\n\treturn commonPrefix;\n}\n\n/**\n * Follows the IETF BCP 47 locale schema with modifications.\n */\nexport const pattern =\n\t\"^((?<grandfathered>(en-GB-oed|i-ami|i-bnn|i-default|i-enochian|i-hak|i-klingon|i-lux|i-mingo|i-navajo|i-pwn|i-tao|i-tay|i-tsu|sgn-BE-FR|sgn-BE-NL|sgn-CH-DE)|(art-lojban|cel-gaulish|no-bok|no-nyn|zh-guoyu|zh-hakka|zh-min|zh-min-nan|zh-xiang))|((?<language>([A-Za-z]{2,3}(-(?<extlang>[A-Za-z]{3}(-[A-Za-z]{3}){0,2}))?))(-(?<script>[A-Za-z]{4}))?(-(?<region>[A-Za-z]{2}|[0-9]{3}))?(-(?<variant>[A-Za-z0-9]{5,8}|[0-9][A-Za-z0-9]{3}))*))$\";\n\n// const isValidlocale = (locale: string): boolean =>\n// \tRegExp(`${pattern}`).test(locale);\n"]}
@@ -6,10 +6,14 @@ export declare const maybeAddMachineTranslation: CliStep<{
6
6
  projectPath: string;
7
7
  root: string;
8
8
  packageJsonPath: string;
9
+ interactive?: boolean;
10
+ machineTranslation?: boolean;
9
11
  }, {
10
12
  fs: typeof import("node:fs/promises");
11
13
  logger: Logger;
12
14
  projectPath: string;
13
15
  root: string;
14
16
  packageJsonPath: string;
17
+ interactive?: boolean;
18
+ machineTranslation?: boolean;
15
19
  }>;
@@ -1,13 +1,16 @@
1
- import { prompt } from "../utils.js";
1
+ import { prompt, shellArgument } from "../utils.js";
2
2
  import { updatePackageJson } from "./update-package-json.js";
3
3
  import path from "node:path";
4
4
  import { INLANG_CLI_VERSION_RANGE } from "./add-inlang-check.js";
5
5
  export const maybeAddMachineTranslation = async (ctx) => {
6
6
  // Prompt for machine translation
7
- const useMachineTranslation = await prompt(`Do you want to set up machine translations?`, {
8
- type: "confirm",
9
- initial: true,
10
- });
7
+ const useMachineTranslation = ctx.machineTranslation ??
8
+ (ctx.interactive === false
9
+ ? false
10
+ : await prompt(`Do you want to set up machine translations?`, {
11
+ type: "confirm",
12
+ initial: true,
13
+ }));
11
14
  if (!useMachineTranslation) {
12
15
  return ctx;
13
16
  }
@@ -31,7 +34,7 @@ export const maybeAddMachineTranslation = async (ctx) => {
31
34
  return scripts;
32
35
  return {
33
36
  ...scripts,
34
- "machine-translate": `inlang machine translate --project ${relativePath}`,
37
+ "machine-translate": `inlang machine translate --project ${shellArgument(relativePath)}`,
35
38
  };
36
39
  },
37
40
  })(ctx);
@@ -44,6 +47,8 @@ export const maybeAddMachineTranslation = async (ctx) => {
44
47
  "2. Add a machine-translate script to package.json",
45
48
  error,
46
49
  ].join("\n"));
50
+ if (ctx.interactive === false)
51
+ throw error;
47
52
  }
48
53
  return ctx;
49
54
  };
@@ -1 +1 @@
1
- {"version":3,"file":"maybe-add-machine-translation.js","sourceRoot":"","sources":["../../../src/cli/steps/maybe-add-machine-translation.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AAEjE,MAAM,CAAC,MAAM,0BAA0B,GAenC,KAAK,EAAE,GAAG,EAAE,EAAE;IACjB,iCAAiC;IACjC,MAAM,qBAAqB,GAAG,MAAM,MAAM,CACzC,6CAA6C,EAC7C;QACC,IAAI,EAAE,SAAS;QACf,OAAO,EAAE,IAAI;KACb,CACD,CAAC;IAEF,IAAI,CAAC,qBAAqB,EAAE,CAAC;QAC5B,OAAO,GAAG,CAAC;IACZ,CAAC;IAED,IAAI,CAAC;QACJ,mDAAmD;QACnD,MAAM,YAAY,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,WAAW,CAAC,CAAC;QAE9D,2FAA2F;QAC3F,MAAM,iBAAiB,CAAC;YACvB,eAAe,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;gBAClC,iBAAiB;gBACjB,IAAI,OAAO,CAAC,aAAa,CAAC;oBAAE,OAAO,OAAO,CAAC;gBAC3C,OAAO;oBACN,GAAG,OAAO;oBACV,aAAa,EAAE,wBAAwB;iBACvC,CAAC;YACH,CAAC;YACD,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;gBAC1B,iBAAiB;gBACjB,IAAI,OAAO,CAAC,mBAAmB,CAAC;oBAAE,OAAO,OAAO,CAAC;gBACjD,OAAO;oBACN,GAAG,OAAO;oBACV,mBAAmB,EAAE,sCAAsC,YAAY,EAAE;iBACzE,CAAC;YACH,CAAC;SACD,CAAC,CAAC,GAAG,CAAC,CAAC;QAER,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,mDAAmD,CAAC,CAAC;IACzE,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,GAAG,CAAC,MAAM,CAAC,KAAK,CACf;YACC,+DAA+D;YAC/D,uCAAuC;YACvC,mDAAmD;YACnD,KAAK;SACL,CAAC,IAAI,CAAC,IAAI,CAAC,CACZ,CAAC;IACH,CAAC;IAED,OAAO,GAAG,CAAC;AACZ,CAAC,CAAC","sourcesContent":["import type { Logger } from \"../../services/logger/index.js\";\nimport type { CliStep } from \"../utils.js\";\nimport { prompt } from \"../utils.js\";\nimport { updatePackageJson } from \"./update-package-json.js\";\nimport path from \"node:path\";\nimport { INLANG_CLI_VERSION_RANGE } from \"./add-inlang-check.js\";\n\nexport const maybeAddMachineTranslation: CliStep<\n\t{\n\t\tfs: typeof import(\"node:fs/promises\");\n\t\tlogger: Logger;\n\t\tprojectPath: string;\n\t\troot: string;\n\t\tpackageJsonPath: string;\n\t},\n\t{\n\t\tfs: typeof import(\"node:fs/promises\");\n\t\tlogger: Logger;\n\t\tprojectPath: string;\n\t\troot: string;\n\t\tpackageJsonPath: string;\n\t}\n> = async (ctx) => {\n\t// Prompt for machine translation\n\tconst useMachineTranslation = await prompt(\n\t\t`Do you want to set up machine translations?`,\n\t\t{\n\t\t\ttype: \"confirm\",\n\t\t\tinitial: true,\n\t\t}\n\t);\n\n\tif (!useMachineTranslation) {\n\t\treturn ctx;\n\t}\n\n\ttry {\n\t\t// Determine the relative path from root to project\n\t\tconst relativePath = path.relative(ctx.root, ctx.projectPath);\n\n\t\t// Use updatePackageJson to add @inlang/cli to devDependencies and machine-translate script\n\t\tawait updatePackageJson({\n\t\t\tdevDependencies: async (devDeps) => {\n\t\t\t\t// exists already\n\t\t\t\tif (devDeps[\"@inlang/cli\"]) return devDeps;\n\t\t\t\treturn {\n\t\t\t\t\t...devDeps,\n\t\t\t\t\t\"@inlang/cli\": INLANG_CLI_VERSION_RANGE,\n\t\t\t\t};\n\t\t\t},\n\t\t\tscripts: async (scripts) => {\n\t\t\t\t// exists already\n\t\t\t\tif (scripts[\"machine-translate\"]) return scripts;\n\t\t\t\treturn {\n\t\t\t\t\t...scripts,\n\t\t\t\t\t\"machine-translate\": `inlang machine translate --project ${relativePath}`,\n\t\t\t\t};\n\t\t\t},\n\t\t})(ctx);\n\n\t\tctx.logger.success(\"Added a machine-translate script to package.json.\");\n\t} catch (error) {\n\t\tctx.logger.error(\n\t\t\t[\n\t\t\t\t\"Failed to set up machine translation. Please add it manually:\",\n\t\t\t\t\"1. Add @inlang/cli to devDependencies\",\n\t\t\t\t\"2. Add a machine-translate script to package.json\",\n\t\t\t\terror,\n\t\t\t].join(\"\\n\")\n\t\t);\n\t}\n\n\treturn ctx;\n};\n"]}
1
+ {"version":3,"file":"maybe-add-machine-translation.js","sourceRoot":"","sources":["../../../src/cli/steps/maybe-add-machine-translation.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AAEjE,MAAM,CAAC,MAAM,0BAA0B,GAmBnC,KAAK,EAAE,GAAG,EAAE,EAAE;IACjB,iCAAiC;IACjC,MAAM,qBAAqB,GAC1B,GAAG,CAAC,kBAAkB;QACtB,CAAC,GAAG,CAAC,WAAW,KAAK,KAAK;YACzB,CAAC,CAAC,KAAK;YACP,CAAC,CAAC,MAAM,MAAM,CAAC,6CAA6C,EAAE;gBAC5D,IAAI,EAAE,SAAS;gBACf,OAAO,EAAE,IAAI;aACb,CAAC,CAAC,CAAC;IAEP,IAAI,CAAC,qBAAqB,EAAE,CAAC;QAC5B,OAAO,GAAG,CAAC;IACZ,CAAC;IAED,IAAI,CAAC;QACJ,mDAAmD;QACnD,MAAM,YAAY,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,WAAW,CAAC,CAAC;QAE9D,2FAA2F;QAC3F,MAAM,iBAAiB,CAAC;YACvB,eAAe,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;gBAClC,iBAAiB;gBACjB,IAAI,OAAO,CAAC,aAAa,CAAC;oBAAE,OAAO,OAAO,CAAC;gBAC3C,OAAO;oBACN,GAAG,OAAO;oBACV,aAAa,EAAE,wBAAwB;iBACvC,CAAC;YACH,CAAC;YACD,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;gBAC1B,iBAAiB;gBACjB,IAAI,OAAO,CAAC,mBAAmB,CAAC;oBAAE,OAAO,OAAO,CAAC;gBACjD,OAAO;oBACN,GAAG,OAAO;oBACV,mBAAmB,EAAE,sCAAsC,aAAa,CAAC,YAAY,CAAC,EAAE;iBACxF,CAAC;YACH,CAAC;SACD,CAAC,CAAC,GAAG,CAAC,CAAC;QAER,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,mDAAmD,CAAC,CAAC;IACzE,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,GAAG,CAAC,MAAM,CAAC,KAAK,CACf;YACC,+DAA+D;YAC/D,uCAAuC;YACvC,mDAAmD;YACnD,KAAK;SACL,CAAC,IAAI,CAAC,IAAI,CAAC,CACZ,CAAC;QACF,IAAI,GAAG,CAAC,WAAW,KAAK,KAAK;YAAE,MAAM,KAAK,CAAC;IAC5C,CAAC;IAED,OAAO,GAAG,CAAC;AACZ,CAAC,CAAC","sourcesContent":["import type { Logger } from \"../../services/logger/index.js\";\nimport type { CliStep } from \"../utils.js\";\nimport { prompt, shellArgument } from \"../utils.js\";\nimport { updatePackageJson } from \"./update-package-json.js\";\nimport path from \"node:path\";\nimport { INLANG_CLI_VERSION_RANGE } from \"./add-inlang-check.js\";\n\nexport const maybeAddMachineTranslation: CliStep<\n\t{\n\t\tfs: typeof import(\"node:fs/promises\");\n\t\tlogger: Logger;\n\t\tprojectPath: string;\n\t\troot: string;\n\t\tpackageJsonPath: string;\n\t\tinteractive?: boolean;\n\t\tmachineTranslation?: boolean;\n\t},\n\t{\n\t\tfs: typeof import(\"node:fs/promises\");\n\t\tlogger: Logger;\n\t\tprojectPath: string;\n\t\troot: string;\n\t\tpackageJsonPath: string;\n\t\tinteractive?: boolean;\n\t\tmachineTranslation?: boolean;\n\t}\n> = async (ctx) => {\n\t// Prompt for machine translation\n\tconst useMachineTranslation =\n\t\tctx.machineTranslation ??\n\t\t(ctx.interactive === false\n\t\t\t? false\n\t\t\t: await prompt(`Do you want to set up machine translations?`, {\n\t\t\t\t\ttype: \"confirm\",\n\t\t\t\t\tinitial: true,\n\t\t\t\t}));\n\n\tif (!useMachineTranslation) {\n\t\treturn ctx;\n\t}\n\n\ttry {\n\t\t// Determine the relative path from root to project\n\t\tconst relativePath = path.relative(ctx.root, ctx.projectPath);\n\n\t\t// Use updatePackageJson to add @inlang/cli to devDependencies and machine-translate script\n\t\tawait updatePackageJson({\n\t\t\tdevDependencies: async (devDeps) => {\n\t\t\t\t// exists already\n\t\t\t\tif (devDeps[\"@inlang/cli\"]) return devDeps;\n\t\t\t\treturn {\n\t\t\t\t\t...devDeps,\n\t\t\t\t\t\"@inlang/cli\": INLANG_CLI_VERSION_RANGE,\n\t\t\t\t};\n\t\t\t},\n\t\t\tscripts: async (scripts) => {\n\t\t\t\t// exists already\n\t\t\t\tif (scripts[\"machine-translate\"]) return scripts;\n\t\t\t\treturn {\n\t\t\t\t\t...scripts,\n\t\t\t\t\t\"machine-translate\": `inlang machine translate --project ${shellArgument(relativePath)}`,\n\t\t\t\t};\n\t\t\t},\n\t\t})(ctx);\n\n\t\tctx.logger.success(\"Added a machine-translate script to package.json.\");\n\t} catch (error) {\n\t\tctx.logger.error(\n\t\t\t[\n\t\t\t\t\"Failed to set up machine translation. Please add it manually:\",\n\t\t\t\t\"1. Add @inlang/cli to devDependencies\",\n\t\t\t\t\"2. Add a machine-translate script to package.json\",\n\t\t\t\terror,\n\t\t\t].join(\"\\n\")\n\t\t);\n\t\tif (ctx.interactive === false) throw error;\n\t}\n\n\treturn ctx;\n};\n"]}
@@ -5,4 +5,6 @@ export declare const maybeAddSherlock: CliStep<{
5
5
  fs: typeof import("node:fs/promises");
6
6
  logger: Logger;
7
7
  project: InlangProject;
8
+ interactive?: boolean;
9
+ sherlock?: boolean;
8
10
  }, unknown>;
@@ -1,9 +1,12 @@
1
1
  import { prompt } from "../utils.js";
2
2
  import * as Sherlock from "@inlang/recommend-sherlock";
3
3
  export const maybeAddSherlock = async (ctx) => {
4
+ if (ctx.sherlock === false ||
5
+ (ctx.interactive === false && ctx.sherlock !== true))
6
+ return ctx;
4
7
  const isCertainlyVsCode = process?.env?.TERM_PROGRAM === "vscode";
5
- let isUsingVsCode = isCertainlyVsCode;
6
- if (!isCertainlyVsCode) {
8
+ let isUsingVsCode = ctx.sherlock === true || isCertainlyVsCode;
9
+ if (!isCertainlyVsCode && ctx.sherlock !== true) {
7
10
  isUsingVsCode = await prompt(`Are you using Visual Studio Code or a compatible fork (like Cursor)?`, {
8
11
  type: "confirm",
9
12
  initial: true,
@@ -11,10 +14,11 @@ export const maybeAddSherlock = async (ctx) => {
11
14
  }
12
15
  if (isUsingVsCode === false)
13
16
  return ctx;
14
- const shouldAddSherlock = await prompt(`Do you want to use the Sherlock VSCode (or Cursor) extension for a better DX?`, {
15
- type: "confirm",
16
- initial: true,
17
- });
17
+ const shouldAddSherlock = ctx.sherlock ??
18
+ (await prompt(`Do you want to use the Sherlock VSCode (or Cursor) extension for a better DX?`, {
19
+ type: "confirm",
20
+ initial: true,
21
+ }));
18
22
  if (shouldAddSherlock === false)
19
23
  return ctx;
20
24
  const settings = await ctx.project.settings.get();
@@ -36,6 +40,8 @@ export const maybeAddSherlock = async (ctx) => {
36
40
  "Failed to add the Sherlock VSCode extension. Please open an issue",
37
41
  error,
38
42
  ].join("\n"));
43
+ if (ctx.interactive === false)
44
+ throw error;
39
45
  }
40
46
  return ctx;
41
47
  };
@@ -1 +1 @@
1
- {"version":3,"file":"maybe-add-sherlock.js","sourceRoot":"","sources":["../../../src/cli/steps/maybe-add-sherlock.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAGrC,OAAO,KAAK,QAAQ,MAAM,4BAA4B,CAAC;AAEvD,MAAM,CAAC,MAAM,gBAAgB,GAOzB,KAAK,EAAE,GAAG,EAAE,EAAE;IACjB,MAAM,iBAAiB,GAAG,OAAO,EAAE,GAAG,EAAE,YAAY,KAAK,QAAQ,CAAC;IAClE,IAAI,aAAa,GAAG,iBAAiB,CAAC;IAEtC,IAAI,CAAC,iBAAiB,EAAE,CAAC;QACxB,aAAa,GAAG,MAAM,MAAM,CAC3B,sEAAsE,EACtE;YACC,IAAI,EAAE,SAAS;YACf,OAAO,EAAE,IAAI;SACb,CACD,CAAC;IACH,CAAC;IACD,IAAI,aAAa,KAAK,KAAK;QAAE,OAAO,GAAG,CAAC;IAExC,MAAM,iBAAiB,GAAG,MAAM,MAAM,CACrC,+EAA+E,EAC/E;QACC,IAAI,EAAE,SAAS;QACf,OAAO,EAAE,IAAI;KACb,CACD,CAAC;IACF,IAAI,iBAAiB,KAAK,KAAK;QAAE,OAAO,GAAG,CAAC;IAE5C,MAAM,QAAQ,GAAG,MAAM,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC;IAElD,sCAAsC;IACtC,IACC,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,2BAA2B,CAAC,CAAC;QACtE,KAAK,EACJ,CAAC;QACF,oCAAoC;QACpC,QAAQ,CAAC,OAAO,CAAC,IAAI,CACpB,oFAAoF,CACpF,CAAC;QACF,MAAM,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAC1C,CAAC;IAED,IAAI,CAAC;QACJ,IAAI,CAAC,CAAC,MAAM,QAAQ,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC;YACjD,MAAM,QAAQ,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC;YACnC,GAAG,CAAC,MAAM,CAAC,OAAO,CACjB,uEAAuE,CACvE,CAAC;QACH,CAAC;IACF,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,GAAG,CAAC,MAAM,CAAC,KAAK,CACf;YACC,mEAAmE;YACnE,KAAK;SACL,CAAC,IAAI,CAAC,IAAI,CAAC,CACZ,CAAC;IACH,CAAC;IAED,OAAO,GAAG,CAAC;AACZ,CAAC,CAAC","sourcesContent":["import type { Logger } from \"../../services/logger/index.js\";\nimport { prompt } from \"../utils.js\";\nimport type { CliStep } from \"../utils.js\";\nimport type { InlangProject } from \"@inlang/sdk\";\nimport * as Sherlock from \"@inlang/recommend-sherlock\";\n\nexport const maybeAddSherlock: CliStep<\n\t{\n\t\tfs: typeof import(\"node:fs/promises\");\n\t\tlogger: Logger;\n\t\tproject: InlangProject;\n\t},\n\tunknown\n> = async (ctx) => {\n\tconst isCertainlyVsCode = process?.env?.TERM_PROGRAM === \"vscode\";\n\tlet isUsingVsCode = isCertainlyVsCode;\n\n\tif (!isCertainlyVsCode) {\n\t\tisUsingVsCode = await prompt(\n\t\t\t`Are you using Visual Studio Code or a compatible fork (like Cursor)?`,\n\t\t\t{\n\t\t\t\ttype: \"confirm\",\n\t\t\t\tinitial: true,\n\t\t\t}\n\t\t);\n\t}\n\tif (isUsingVsCode === false) return ctx;\n\n\tconst shouldAddSherlock = await prompt(\n\t\t`Do you want to use the Sherlock VSCode (or Cursor) extension for a better DX?`,\n\t\t{\n\t\t\ttype: \"confirm\",\n\t\t\tinitial: true,\n\t\t}\n\t);\n\tif (shouldAddSherlock === false) return ctx;\n\n\tconst settings = await ctx.project.settings.get();\n\n\t// m function matcher is not installed\n\tif (\n\t\tsettings.modules?.some((m) => m.includes(\"plugin-m-function-matcher\")) ===\n\t\tfalse\n\t) {\n\t\t// add the m function matcher plugin\n\t\tsettings.modules.push(\n\t\t\t\"https://cdn.jsdelivr.net/npm/@inlang/plugin-m-function-matcher@2.3.0/dist/index.js\"\n\t\t);\n\t\tawait ctx.project.settings.set(settings);\n\t}\n\n\ttry {\n\t\tif (!(await Sherlock.isAdopted({ fs: ctx.fs }))) {\n\t\t\tawait Sherlock.add({ fs: ctx.fs });\n\t\t\tctx.logger.success(\n\t\t\t\t\"Added the Sherlock VSCode extension to the workspace recommendations.\"\n\t\t\t);\n\t\t}\n\t} catch (error) {\n\t\tctx.logger.error(\n\t\t\t[\n\t\t\t\t\"Failed to add the Sherlock VSCode extension. Please open an issue\",\n\t\t\t\terror,\n\t\t\t].join(\"\\n\")\n\t\t);\n\t}\n\n\treturn ctx;\n};\n"]}
1
+ {"version":3,"file":"maybe-add-sherlock.js","sourceRoot":"","sources":["../../../src/cli/steps/maybe-add-sherlock.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAGrC,OAAO,KAAK,QAAQ,MAAM,4BAA4B,CAAC;AAEvD,MAAM,CAAC,MAAM,gBAAgB,GASzB,KAAK,EAAE,GAAG,EAAE,EAAE;IACjB,IACC,GAAG,CAAC,QAAQ,KAAK,KAAK;QACtB,CAAC,GAAG,CAAC,WAAW,KAAK,KAAK,IAAI,GAAG,CAAC,QAAQ,KAAK,IAAI,CAAC;QAEpD,OAAO,GAAG,CAAC;IACZ,MAAM,iBAAiB,GAAG,OAAO,EAAE,GAAG,EAAE,YAAY,KAAK,QAAQ,CAAC;IAClE,IAAI,aAAa,GAAG,GAAG,CAAC,QAAQ,KAAK,IAAI,IAAI,iBAAiB,CAAC;IAE/D,IAAI,CAAC,iBAAiB,IAAI,GAAG,CAAC,QAAQ,KAAK,IAAI,EAAE,CAAC;QACjD,aAAa,GAAG,MAAM,MAAM,CAC3B,sEAAsE,EACtE;YACC,IAAI,EAAE,SAAS;YACf,OAAO,EAAE,IAAI;SACb,CACD,CAAC;IACH,CAAC;IACD,IAAI,aAAa,KAAK,KAAK;QAAE,OAAO,GAAG,CAAC;IAExC,MAAM,iBAAiB,GACtB,GAAG,CAAC,QAAQ;QACZ,CAAC,MAAM,MAAM,CACZ,+EAA+E,EAC/E;YACC,IAAI,EAAE,SAAS;YACf,OAAO,EAAE,IAAI;SACb,CACD,CAAC,CAAC;IACJ,IAAI,iBAAiB,KAAK,KAAK;QAAE,OAAO,GAAG,CAAC;IAE5C,MAAM,QAAQ,GAAG,MAAM,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC;IAElD,sCAAsC;IACtC,IACC,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,2BAA2B,CAAC,CAAC;QACtE,KAAK,EACJ,CAAC;QACF,oCAAoC;QACpC,QAAQ,CAAC,OAAO,CAAC,IAAI,CACpB,oFAAoF,CACpF,CAAC;QACF,MAAM,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAC1C,CAAC;IAED,IAAI,CAAC;QACJ,IAAI,CAAC,CAAC,MAAM,QAAQ,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC;YACjD,MAAM,QAAQ,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC;YACnC,GAAG,CAAC,MAAM,CAAC,OAAO,CACjB,uEAAuE,CACvE,CAAC;QACH,CAAC;IACF,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,GAAG,CAAC,MAAM,CAAC,KAAK,CACf;YACC,mEAAmE;YACnE,KAAK;SACL,CAAC,IAAI,CAAC,IAAI,CAAC,CACZ,CAAC;QACF,IAAI,GAAG,CAAC,WAAW,KAAK,KAAK;YAAE,MAAM,KAAK,CAAC;IAC5C,CAAC;IAED,OAAO,GAAG,CAAC;AACZ,CAAC,CAAC","sourcesContent":["import type { Logger } from \"../../services/logger/index.js\";\nimport { prompt } from \"../utils.js\";\nimport type { CliStep } from \"../utils.js\";\nimport type { InlangProject } from \"@inlang/sdk\";\nimport * as Sherlock from \"@inlang/recommend-sherlock\";\n\nexport const maybeAddSherlock: CliStep<\n\t{\n\t\tfs: typeof import(\"node:fs/promises\");\n\t\tlogger: Logger;\n\t\tproject: InlangProject;\n\t\tinteractive?: boolean;\n\t\tsherlock?: boolean;\n\t},\n\tunknown\n> = async (ctx) => {\n\tif (\n\t\tctx.sherlock === false ||\n\t\t(ctx.interactive === false && ctx.sherlock !== true)\n\t)\n\t\treturn ctx;\n\tconst isCertainlyVsCode = process?.env?.TERM_PROGRAM === \"vscode\";\n\tlet isUsingVsCode = ctx.sherlock === true || isCertainlyVsCode;\n\n\tif (!isCertainlyVsCode && ctx.sherlock !== true) {\n\t\tisUsingVsCode = await prompt(\n\t\t\t`Are you using Visual Studio Code or a compatible fork (like Cursor)?`,\n\t\t\t{\n\t\t\t\ttype: \"confirm\",\n\t\t\t\tinitial: true,\n\t\t\t}\n\t\t);\n\t}\n\tif (isUsingVsCode === false) return ctx;\n\n\tconst shouldAddSherlock =\n\t\tctx.sherlock ??\n\t\t(await prompt(\n\t\t\t`Do you want to use the Sherlock VSCode (or Cursor) extension for a better DX?`,\n\t\t\t{\n\t\t\t\ttype: \"confirm\",\n\t\t\t\tinitial: true,\n\t\t\t}\n\t\t));\n\tif (shouldAddSherlock === false) return ctx;\n\n\tconst settings = await ctx.project.settings.get();\n\n\t// m function matcher is not installed\n\tif (\n\t\tsettings.modules?.some((m) => m.includes(\"plugin-m-function-matcher\")) ===\n\t\tfalse\n\t) {\n\t\t// add the m function matcher plugin\n\t\tsettings.modules.push(\n\t\t\t\"https://cdn.jsdelivr.net/npm/@inlang/plugin-m-function-matcher@2.3.0/dist/index.js\"\n\t\t);\n\t\tawait ctx.project.settings.set(settings);\n\t}\n\n\ttry {\n\t\tif (!(await Sherlock.isAdopted({ fs: ctx.fs }))) {\n\t\t\tawait Sherlock.add({ fs: ctx.fs });\n\t\t\tctx.logger.success(\n\t\t\t\t\"Added the Sherlock VSCode extension to the workspace recommendations.\"\n\t\t\t);\n\t\t}\n\t} catch (error) {\n\t\tctx.logger.error(\n\t\t\t[\n\t\t\t\t\"Failed to add the Sherlock VSCode extension. Please open an issue\",\n\t\t\t\terror,\n\t\t\t].join(\"\\n\")\n\t\t);\n\t\tif (ctx.interactive === false) throw error;\n\t}\n\n\treturn ctx;\n};\n"]}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,44 @@
1
+ import { test, expect, vi, afterEach } from "vitest";
2
+ import { memfs } from "memfs";
3
+ import * as Sherlock from "@inlang/recommend-sherlock";
4
+ import { Logger } from "../../services/logger/index.js";
5
+ import { getNewProjectTemplate } from "../defaults.js";
6
+ import { maybeAddSherlock } from "./maybe-add-sherlock.js";
7
+ vi.mock("@inlang/recommend-sherlock", () => ({
8
+ isAdopted: vi.fn().mockResolvedValue(false),
9
+ add: vi.fn().mockResolvedValue(undefined),
10
+ }));
11
+ afterEach(() => {
12
+ vi.unstubAllEnvs();
13
+ vi.clearAllMocks();
14
+ });
15
+ test("headless setup skips editor recommendations unless explicitly requested", async () => {
16
+ vi.stubEnv("TERM_PROGRAM", "vscode");
17
+ const fs = memfs().fs;
18
+ const project = {
19
+ settings: { get: vi.fn().mockResolvedValue(getNewProjectTemplate()) },
20
+ };
21
+ await maybeAddSherlock({
22
+ fs: fs.promises,
23
+ project,
24
+ logger: new Logger({ silent: true, prefix: false }),
25
+ interactive: false,
26
+ });
27
+ expect(Sherlock.add).not.toHaveBeenCalled();
28
+ });
29
+ test("explicit editor opt-in works headlessly outside a VSCode terminal", async () => {
30
+ vi.stubEnv("TERM_PROGRAM", "");
31
+ const fs = memfs().fs;
32
+ const project = {
33
+ settings: { get: vi.fn().mockResolvedValue(getNewProjectTemplate()) },
34
+ };
35
+ await maybeAddSherlock({
36
+ fs: fs.promises,
37
+ project,
38
+ logger: new Logger({ silent: true, prefix: false }),
39
+ interactive: false,
40
+ sherlock: true,
41
+ });
42
+ expect(Sherlock.add).toHaveBeenCalledOnce();
43
+ });
44
+ //# sourceMappingURL=maybe-add-sherlock.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"maybe-add-sherlock.test.js","sourceRoot":"","sources":["../../../src/cli/steps/maybe-add-sherlock.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AACrD,OAAO,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC;AAE9B,OAAO,KAAK,QAAQ,MAAM,4BAA4B,CAAC;AACvD,OAAO,EAAE,MAAM,EAAE,MAAM,gCAAgC,CAAC;AACxD,OAAO,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AACvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAE3D,EAAE,CAAC,IAAI,CAAC,4BAA4B,EAAE,GAAG,EAAE,CAAC,CAAC;IAC5C,SAAS,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,KAAK,CAAC;IAC3C,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,SAAS,CAAC;CACzC,CAAC,CAAC,CAAC;AACJ,SAAS,CAAC,GAAG,EAAE;IACd,EAAE,CAAC,aAAa,EAAE,CAAC;IACnB,EAAE,CAAC,aAAa,EAAE,CAAC;AACpB,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,yEAAyE,EAAE,KAAK,IAAI,EAAE;IAC1F,EAAE,CAAC,OAAO,CAAC,cAAc,EAAE,QAAQ,CAAC,CAAC;IACrC,MAAM,EAAE,GAAG,KAAK,EAAE,CAAC,EAAyC,CAAC;IAC7D,MAAM,OAAO,GAAG;QACf,QAAQ,EAAE,EAAE,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,qBAAqB,EAAE,CAAC,EAAE;KACzC,CAAC;IAC9B,MAAM,gBAAgB,CAAC;QACtB,EAAE,EAAE,EAAE,CAAC,QAAQ;QACf,OAAO;QACP,MAAM,EAAE,IAAI,MAAM,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;QACnD,WAAW,EAAE,KAAK;KAClB,CAAC,CAAC;IACH,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;AAC7C,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,mEAAmE,EAAE,KAAK,IAAI,EAAE;IACpF,EAAE,CAAC,OAAO,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC;IAC/B,MAAM,EAAE,GAAG,KAAK,EAAE,CAAC,EAAyC,CAAC;IAC7D,MAAM,OAAO,GAAG;QACf,QAAQ,EAAE,EAAE,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,qBAAqB,EAAE,CAAC,EAAE;KACzC,CAAC;IAC9B,MAAM,gBAAgB,CAAC;QACtB,EAAE,EAAE,EAAE,CAAC,QAAQ;QACf,OAAO;QACP,MAAM,EAAE,IAAI,MAAM,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;QACnD,WAAW,EAAE,KAAK;QAClB,QAAQ,EAAE,IAAI;KACd,CAAC,CAAC;IACH,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,oBAAoB,EAAE,CAAC;AAC7C,CAAC,CAAC,CAAC","sourcesContent":["import { test, expect, vi, afterEach } from \"vitest\";\nimport { memfs } from \"memfs\";\nimport type { InlangProject } from \"@inlang/sdk\";\nimport * as Sherlock from \"@inlang/recommend-sherlock\";\nimport { Logger } from \"../../services/logger/index.js\";\nimport { getNewProjectTemplate } from \"../defaults.js\";\nimport { maybeAddSherlock } from \"./maybe-add-sherlock.js\";\n\nvi.mock(\"@inlang/recommend-sherlock\", () => ({\n\tisAdopted: vi.fn().mockResolvedValue(false),\n\tadd: vi.fn().mockResolvedValue(undefined),\n}));\nafterEach(() => {\n\tvi.unstubAllEnvs();\n\tvi.clearAllMocks();\n});\n\ntest(\"headless setup skips editor recommendations unless explicitly requested\", async () => {\n\tvi.stubEnv(\"TERM_PROGRAM\", \"vscode\");\n\tconst fs = memfs().fs as unknown as typeof import(\"node:fs\");\n\tconst project = {\n\t\tsettings: { get: vi.fn().mockResolvedValue(getNewProjectTemplate()) },\n\t} as unknown as InlangProject;\n\tawait maybeAddSherlock({\n\t\tfs: fs.promises,\n\t\tproject,\n\t\tlogger: new Logger({ silent: true, prefix: false }),\n\t\tinteractive: false,\n\t});\n\texpect(Sherlock.add).not.toHaveBeenCalled();\n});\n\ntest(\"explicit editor opt-in works headlessly outside a VSCode terminal\", async () => {\n\tvi.stubEnv(\"TERM_PROGRAM\", \"\");\n\tconst fs = memfs().fs as unknown as typeof import(\"node:fs\");\n\tconst project = {\n\t\tsettings: { get: vi.fn().mockResolvedValue(getNewProjectTemplate()) },\n\t} as unknown as InlangProject;\n\tawait maybeAddSherlock({\n\t\tfs: fs.promises,\n\t\tproject,\n\t\tlogger: new Logger({ silent: true, prefix: false }),\n\t\tinteractive: false,\n\t\tsherlock: true,\n\t});\n\texpect(Sherlock.add).toHaveBeenCalledOnce();\n});\n"]}
@@ -2,6 +2,8 @@ import type { Logger } from "../../services/logger/index.js";
2
2
  import type { CliStep } from "../utils.js";
3
3
  export declare const promptForOutdir: CliStep<{
4
4
  logger: Logger;
5
+ interactive?: boolean;
6
+ outdir?: string;
5
7
  }, {
6
8
  /** Relative path to the output directory */
7
9
  outdir: string;
@@ -1,6 +1,10 @@
1
1
  import { DEFAULT_OUTDIR } from "../../services/config/defaults.js";
2
2
  import { prompt } from "../utils.js";
3
3
  export const promptForOutdir = async (ctx) => {
4
+ if (ctx.outdir !== undefined)
5
+ return { ...ctx, outdir: ctx.outdir };
6
+ if (ctx.interactive === false)
7
+ return { ...ctx, outdir: DEFAULT_OUTDIR };
4
8
  const response = await prompt("Which outdir should Paraglide write generated files to?", {
5
9
  type: "text",
6
10
  initial: DEFAULT_OUTDIR,
@@ -1 +1 @@
1
- {"version":3,"file":"prompt-for-outdir.js","sourceRoot":"","sources":["../../../src/cli/steps/prompt-for-outdir.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC;AACnE,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAGrC,MAAM,CAAC,MAAM,eAAe,GAQxB,KAAK,EAAE,GAAG,EAAE,EAAE;IACjB,MAAM,QAAQ,GAAG,MAAM,MAAM,CAC5B,yDAAyD,EACzD;QACC,IAAI,EAAE,MAAM;QACZ,OAAO,EAAE,cAAc;QACvB,OAAO,EAAE,cAAc;QACvB,WAAW,EACV,8EAA8E;KAC/E,CACD,CAAC;IAEF,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QAChC,GAAG,CAAC,MAAM,CAAC,IAAI,CACd,sEAAsE,CACtE,CAAC;QACF,OAAO,MAAM,eAAe,CAAC,GAAG,CAAC,CAAC;IACnC,CAAC;IAED,OAAO;QACN,GAAG,GAAG;QACN,MAAM,EAAE,QAAQ;KAChB,CAAC;AACH,CAAC,CAAC","sourcesContent":["import type { Logger } from \"../../services/logger/index.js\";\nimport { DEFAULT_OUTDIR } from \"../../services/config/defaults.js\";\nimport { prompt } from \"../utils.js\";\nimport type { CliStep } from \"../utils.js\";\n\nexport const promptForOutdir: CliStep<\n\t{\n\t\tlogger: Logger;\n\t},\n\t{\n\t\t/** Relative path to the output directory */\n\t\toutdir: string;\n\t}\n> = async (ctx) => {\n\tconst response = await prompt(\n\t\t\"Which outdir should Paraglide write generated files to?\",\n\t\t{\n\t\t\ttype: \"text\",\n\t\t\tinitial: DEFAULT_OUTDIR,\n\t\t\tdefault: DEFAULT_OUTDIR,\n\t\t\tplaceholder:\n\t\t\t\t\"Relative path from the package root to the desired compiler output directory\",\n\t\t}\n\t);\n\n\tif (!response.startsWith(\"./\")) {\n\t\tctx.logger.warn(\n\t\t\t\"You must enter a valid relative path starting from the package root.\"\n\t\t);\n\t\treturn await promptForOutdir(ctx);\n\t}\n\n\treturn {\n\t\t...ctx,\n\t\toutdir: response,\n\t};\n};\n"]}
1
+ {"version":3,"file":"prompt-for-outdir.js","sourceRoot":"","sources":["../../../src/cli/steps/prompt-for-outdir.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC;AACnE,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAGrC,MAAM,CAAC,MAAM,eAAe,GAUxB,KAAK,EAAE,GAAG,EAAE,EAAE;IACjB,IAAI,GAAG,CAAC,MAAM,KAAK,SAAS;QAAE,OAAO,EAAE,GAAG,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,CAAC;IACpE,IAAI,GAAG,CAAC,WAAW,KAAK,KAAK;QAAE,OAAO,EAAE,GAAG,GAAG,EAAE,MAAM,EAAE,cAAc,EAAE,CAAC;IACzE,MAAM,QAAQ,GAAG,MAAM,MAAM,CAC5B,yDAAyD,EACzD;QACC,IAAI,EAAE,MAAM;QACZ,OAAO,EAAE,cAAc;QACvB,OAAO,EAAE,cAAc;QACvB,WAAW,EACV,8EAA8E;KAC/E,CACD,CAAC;IAEF,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QAChC,GAAG,CAAC,MAAM,CAAC,IAAI,CACd,sEAAsE,CACtE,CAAC;QACF,OAAO,MAAM,eAAe,CAAC,GAAG,CAAC,CAAC;IACnC,CAAC;IAED,OAAO;QACN,GAAG,GAAG;QACN,MAAM,EAAE,QAAQ;KAChB,CAAC;AACH,CAAC,CAAC","sourcesContent":["import type { Logger } from \"../../services/logger/index.js\";\nimport { DEFAULT_OUTDIR } from \"../../services/config/defaults.js\";\nimport { prompt } from \"../utils.js\";\nimport type { CliStep } from \"../utils.js\";\n\nexport const promptForOutdir: CliStep<\n\t{\n\t\tlogger: Logger;\n\t\tinteractive?: boolean;\n\t\toutdir?: string;\n\t},\n\t{\n\t\t/** Relative path to the output directory */\n\t\toutdir: string;\n\t}\n> = async (ctx) => {\n\tif (ctx.outdir !== undefined) return { ...ctx, outdir: ctx.outdir };\n\tif (ctx.interactive === false) return { ...ctx, outdir: DEFAULT_OUTDIR };\n\tconst response = await prompt(\n\t\t\"Which outdir should Paraglide write generated files to?\",\n\t\t{\n\t\t\ttype: \"text\",\n\t\t\tinitial: DEFAULT_OUTDIR,\n\t\t\tdefault: DEFAULT_OUTDIR,\n\t\t\tplaceholder:\n\t\t\t\t\"Relative path from the package root to the desired compiler output directory\",\n\t\t}\n\t);\n\n\tif (!response.startsWith(\"./\")) {\n\t\tctx.logger.warn(\n\t\t\t\"You must enter a valid relative path starting from the package root.\"\n\t\t);\n\t\treturn await promptForOutdir(ctx);\n\t}\n\n\treturn {\n\t\t...ctx,\n\t\toutdir: response,\n\t};\n};\n"]}
@@ -14,20 +14,15 @@ export function updatePackageJson(opt) {
14
14
  }
15
15
  catch {
16
16
  ctx.logger.error(`Your ./package.json does not contain valid JSON. Please fix it and try again.`);
17
- process.exit(1);
17
+ throw new Error("package.json must contain a valid JSON object.");
18
18
  }
19
- try {
20
- if (opt.dependencies)
21
- pkg.dependencies = await opt.dependencies(pkg.dependencies || {});
22
- if (opt.devDependencies)
23
- pkg.devDependencies = await opt.devDependencies(pkg.devDependencies || {});
24
- if (opt.scripts)
25
- pkg.scripts = await opt.scripts(pkg.scripts || {});
26
- }
27
- catch {
28
- return ctx;
29
- }
30
- await ctx.fs.writeFile("./package.json", stringify(pkg));
19
+ if (opt.dependencies)
20
+ pkg.dependencies = await opt.dependencies(pkg.dependencies || {});
21
+ if (opt.devDependencies)
22
+ pkg.devDependencies = await opt.devDependencies(pkg.devDependencies || {});
23
+ if (opt.scripts)
24
+ pkg.scripts = await opt.scripts(pkg.scripts || {});
25
+ await ctx.fs.writeFile(ctx.packageJsonPath, stringify(pkg));
31
26
  return ctx;
32
27
  };
33
28
  }
@@ -1 +1 @@
1
- {"version":3,"file":"update-package-json.js","sourceRoot":"","sources":["../../../src/cli/steps/update-package-json.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AAEjF,MAAM,UAAU,iBAAiB,CAAC,GAUjC;IAQA,OAAO,KAAK,EAAE,GAAG,EAAE,EAAE;QACpB,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,eAAe,EAAE;YACvD,QAAQ,EAAE,OAAO;SACjB,CAAC,CAAC;QAEH,MAAM,SAAS,GAAG,oBAAoB,CAAC,IAAI,CAAC,CAAC;QAE7C,IAAI,GAAG,CAAC;QACR,IAAI,CAAC;YACJ,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YACvB,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;gBAC7C,MAAM,IAAI,KAAK,EAAE,CAAC;YACnB,CAAC;QACF,CAAC;QAAC,MAAM,CAAC;YACR,GAAG,CAAC,MAAM,CAAC,KAAK,CACf,+EAA+E,CAC/E,CAAC;YACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACjB,CAAC;QAED,IAAI,CAAC;YACJ,IAAI,GAAG,CAAC,YAAY;gBACnB,GAAG,CAAC,YAAY,GAAG,MAAM,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,YAAY,IAAI,EAAE,CAAC,CAAC;YACnE,IAAI,GAAG,CAAC,eAAe;gBACtB,GAAG,CAAC,eAAe,GAAG,MAAM,GAAG,CAAC,eAAe,CAC9C,GAAG,CAAC,eAAe,IAAI,EAAE,CACzB,CAAC;YACH,IAAI,GAAG,CAAC,OAAO;gBAAE,GAAG,CAAC,OAAO,GAAG,MAAM,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC;QACrE,CAAC;QAAC,MAAM,CAAC;YACR,OAAO,GAAG,CAAC;QACZ,CAAC;QACD,MAAM,GAAG,CAAC,EAAE,CAAC,SAAS,CAAC,gBAAgB,EAAE,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC;QACzD,OAAO,GAAG,CAAC;IACZ,CAAC,CAAC;AACH,CAAC","sourcesContent":["import type { Logger } from \"../../services/logger/index.js\";\nimport type { CliStep } from \"../utils.js\";\nimport { detectJsonFormatting } from \"../../utilities/detect-json-formatting.js\";\n\nexport function updatePackageJson(opt: {\n\tdependencies?: (\n\t\tdeps: Record<string, string>\n\t) => Promise<Record<string, string>>;\n\tdevDependencies?: (\n\t\tdevDeps: Record<string, string>\n\t) => Promise<Record<string, string>>;\n\tscripts?: (\n\t\tscripts: Record<string, string>\n\t) => Promise<Record<string, string>>;\n}): CliStep<\n\t{\n\t\tpackageJsonPath: string;\n\t\tfs: typeof import(\"node:fs/promises\");\n\t\tlogger: Logger;\n\t},\n\tunknown\n> {\n\treturn async (ctx) => {\n\t\tconst file = await ctx.fs.readFile(ctx.packageJsonPath, {\n\t\t\tencoding: \"utf-8\",\n\t\t});\n\n\t\tconst stringify = detectJsonFormatting(file);\n\n\t\tlet pkg;\n\t\ttry {\n\t\t\tpkg = JSON.parse(file);\n\t\t\tif (typeof pkg !== \"object\" || pkg === null) {\n\t\t\t\tthrow new Error();\n\t\t\t}\n\t\t} catch {\n\t\t\tctx.logger.error(\n\t\t\t\t`Your ./package.json does not contain valid JSON. Please fix it and try again.`\n\t\t\t);\n\t\t\tprocess.exit(1);\n\t\t}\n\n\t\ttry {\n\t\t\tif (opt.dependencies)\n\t\t\t\tpkg.dependencies = await opt.dependencies(pkg.dependencies || {});\n\t\t\tif (opt.devDependencies)\n\t\t\t\tpkg.devDependencies = await opt.devDependencies(\n\t\t\t\t\tpkg.devDependencies || {}\n\t\t\t\t);\n\t\t\tif (opt.scripts) pkg.scripts = await opt.scripts(pkg.scripts || {});\n\t\t} catch {\n\t\t\treturn ctx;\n\t\t}\n\t\tawait ctx.fs.writeFile(\"./package.json\", stringify(pkg));\n\t\treturn ctx;\n\t};\n}\n"]}
1
+ {"version":3,"file":"update-package-json.js","sourceRoot":"","sources":["../../../src/cli/steps/update-package-json.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AAEjF,MAAM,UAAU,iBAAiB,CAAC,GAUjC;IAQA,OAAO,KAAK,EAAE,GAAG,EAAE,EAAE;QACpB,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,eAAe,EAAE;YACvD,QAAQ,EAAE,OAAO;SACjB,CAAC,CAAC;QAEH,MAAM,SAAS,GAAG,oBAAoB,CAAC,IAAI,CAAC,CAAC;QAE7C,IAAI,GAAG,CAAC;QACR,IAAI,CAAC;YACJ,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YACvB,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;gBAC7C,MAAM,IAAI,KAAK,EAAE,CAAC;YACnB,CAAC;QACF,CAAC;QAAC,MAAM,CAAC;YACR,GAAG,CAAC,MAAM,CAAC,KAAK,CACf,+EAA+E,CAC/E,CAAC;YACF,MAAM,IAAI,KAAK,CAAC,gDAAgD,CAAC,CAAC;QACnE,CAAC;QAED,IAAI,GAAG,CAAC,YAAY;YACnB,GAAG,CAAC,YAAY,GAAG,MAAM,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,YAAY,IAAI,EAAE,CAAC,CAAC;QACnE,IAAI,GAAG,CAAC,eAAe;YACtB,GAAG,CAAC,eAAe,GAAG,MAAM,GAAG,CAAC,eAAe,CAC9C,GAAG,CAAC,eAAe,IAAI,EAAE,CACzB,CAAC;QACH,IAAI,GAAG,CAAC,OAAO;YAAE,GAAG,CAAC,OAAO,GAAG,MAAM,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC;QACpE,MAAM,GAAG,CAAC,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,eAAe,EAAE,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC;QAC5D,OAAO,GAAG,CAAC;IACZ,CAAC,CAAC;AACH,CAAC","sourcesContent":["import type { Logger } from \"../../services/logger/index.js\";\nimport type { CliStep } from \"../utils.js\";\nimport { detectJsonFormatting } from \"../../utilities/detect-json-formatting.js\";\n\nexport function updatePackageJson(opt: {\n\tdependencies?: (\n\t\tdeps: Record<string, string>\n\t) => Promise<Record<string, string>>;\n\tdevDependencies?: (\n\t\tdevDeps: Record<string, string>\n\t) => Promise<Record<string, string>>;\n\tscripts?: (\n\t\tscripts: Record<string, string>\n\t) => Promise<Record<string, string>>;\n}): CliStep<\n\t{\n\t\tpackageJsonPath: string;\n\t\tfs: typeof import(\"node:fs/promises\");\n\t\tlogger: Logger;\n\t},\n\tunknown\n> {\n\treturn async (ctx) => {\n\t\tconst file = await ctx.fs.readFile(ctx.packageJsonPath, {\n\t\t\tencoding: \"utf-8\",\n\t\t});\n\n\t\tconst stringify = detectJsonFormatting(file);\n\n\t\tlet pkg;\n\t\ttry {\n\t\t\tpkg = JSON.parse(file);\n\t\t\tif (typeof pkg !== \"object\" || pkg === null) {\n\t\t\t\tthrow new Error();\n\t\t\t}\n\t\t} catch {\n\t\t\tctx.logger.error(\n\t\t\t\t`Your ./package.json does not contain valid JSON. Please fix it and try again.`\n\t\t\t);\n\t\t\tthrow new Error(\"package.json must contain a valid JSON object.\");\n\t\t}\n\n\t\tif (opt.dependencies)\n\t\t\tpkg.dependencies = await opt.dependencies(pkg.dependencies || {});\n\t\tif (opt.devDependencies)\n\t\t\tpkg.devDependencies = await opt.devDependencies(\n\t\t\t\tpkg.devDependencies || {}\n\t\t\t);\n\t\tif (opt.scripts) pkg.scripts = await opt.scripts(pkg.scripts || {});\n\t\tawait ctx.fs.writeFile(ctx.packageJsonPath, stringify(pkg));\n\t\treturn ctx;\n\t};\n}\n"]}
@@ -3,6 +3,8 @@ import type { Logger } from "../../services/logger/index.js";
3
3
  export declare const maybeUpdateTsConfig: CliStep<{
4
4
  fs: typeof import("node:fs/promises");
5
5
  logger: Logger;
6
+ interactive?: boolean;
7
+ root?: string;
6
8
  }, unknown>;
7
9
  /**
8
10
  * Paraligde JS compiles to JS with JSDoc comments. TypeScript doesn't allow JS files by default.
@@ -10,6 +12,8 @@ export declare const maybeUpdateTsConfig: CliStep<{
10
12
  export declare const maybeUpdateTsConfigAllowJs: CliStep<{
11
13
  fs: typeof import("node:fs/promises");
12
14
  logger: Logger;
15
+ interactive?: boolean;
16
+ root?: string;
13
17
  }, unknown>;
14
18
  /**
15
19
  * Recursively checks whether allowJs is enabled in the provided tsconfig or any
@@ -24,3 +28,5 @@ export declare const maybeUpdateTsConfigAllowJs: CliStep<{
24
28
  * ```
25
29
  */
26
30
  export declare const hasAllowJsEnabled: (tsconfigPath: string, fs: typeof import("node:fs/promises"), visited?: Set<string>) => Promise<boolean>;
31
+ /** Edit one property while retaining comments and unrelated configuration text. */
32
+ export declare function enableAllowJs(text: string): string;