@inlang/paraglide-js 1.0.0-prerelease.2 → 1.0.0-prerelease.4

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 (42) hide show
  1. package/README.md +10 -2
  2. package/dist/cli/commands/compile.d.ts.map +1 -1
  3. package/dist/cli/commands/compile.js +16 -19
  4. package/dist/cli/commands/compile.test.d.ts +2 -0
  5. package/dist/cli/commands/compile.test.d.ts.map +1 -0
  6. package/dist/cli/commands/compile.test.js +77 -0
  7. package/dist/cli/commands/init.d.ts +26 -0
  8. package/dist/cli/commands/init.d.ts.map +1 -0
  9. package/dist/cli/commands/init.js +277 -0
  10. package/dist/cli/commands/init.test.d.ts +2 -0
  11. package/dist/cli/commands/init.test.d.ts.map +1 -0
  12. package/dist/cli/commands/init.test.js +472 -0
  13. package/dist/cli/main.d.ts +0 -8
  14. package/dist/cli/main.d.ts.map +1 -1
  15. package/dist/cli/main.js +12 -21
  16. package/dist/cli/main.test.d.ts +2 -0
  17. package/dist/cli/main.test.d.ts.map +1 -0
  18. package/dist/cli/main.test.js +37 -0
  19. package/dist/cli/state.d.ts +14 -0
  20. package/dist/cli/state.d.ts.map +1 -0
  21. package/dist/cli/state.js +28 -0
  22. package/dist/compiled-output/website/messages.d.ts +73 -0
  23. package/dist/compiled-output/website/messages.js +1543 -0
  24. package/dist/compiled-output/{sveltekit-example → website}/runtime.d.ts +1 -1
  25. package/dist/compiled-output/{react-example → website}/runtime.js +1 -1
  26. package/package.json +4 -1
  27. package/dist/compiled-output/example-javascript/messages.d.ts +0 -7
  28. package/dist/compiled-output/example-javascript/messages.js +0 -42
  29. package/dist/compiled-output/example-javascript/runtime.d.ts +0 -38
  30. package/dist/compiled-output/example-javascript/runtime.js +0 -112
  31. package/dist/compiled-output/react-example/messages.d.ts +0 -7
  32. package/dist/compiled-output/react-example/messages.js +0 -42
  33. package/dist/compiled-output/react-example/runtime.d.ts +0 -38
  34. package/dist/compiled-output/sveltekit-example/messages.d.ts +0 -7
  35. package/dist/compiled-output/sveltekit-example/messages.js +0 -42
  36. package/dist/compiled-output/sveltekit-example/runtime.js +0 -112
  37. package/dist/compiler/jsdocFromParams.d.ts +0 -12
  38. package/dist/compiler/jsdocFromParams.d.ts.map +0 -1
  39. package/dist/compiler/jsdocFromParams.js +0 -17
  40. package/dist/compiler/jsdocFromParams.test.d.ts +0 -2
  41. package/dist/compiler/jsdocFromParams.test.d.ts.map +0 -1
  42. package/dist/compiler/jsdocFromParams.test.js +0 -6
package/README.md CHANGED
@@ -1,6 +1,9 @@
1
1
  # @inlang/paraglide-js
2
2
 
3
- ## ATTENTION: Paraglide is in pre-release mode. Discuss the API at https://github.com/inlang/monorepo/discussions/1464
3
+ <!-- ## ATTENTION: Paraglide is in pre-release mode. Discuss the API at https://github.com/inlang/monorepo/discussions/1464 -->
4
+ <doc-links>
5
+ <doc-link title="ATTENTION: Paraglide is in pre-release mode." icon="mdi:github" href="https://github.com/inlang/monorepo/discussions/1464" description="Discuss the API on GitHub."></doc-link>
6
+ </doc-links>
4
7
 
5
8
  <doc-gallery>TODO: adapter gallery</doc-gallery>
6
9
 
@@ -60,11 +63,16 @@ npm install @inlang/paraglide-js
60
63
  ```diff
61
64
  {
62
65
  "scripts": {
63
- + "build": "paraglide-js compile --namespace <your project name>"
66
+ + "build": "paraglide-js compile --namespace <namespace>"
64
67
  }
65
68
  }
66
69
  ```
67
70
 
71
+ | compile | [options] | | |
72
+ |---------|-------------|----------|----------------------------------|
73
+ | | --project | \<path\> | default: "./project.inlang.json" |
74
+ | | --namespace | \<name\> | required |
75
+
68
76
 
69
77
  # Architecture
70
78
 
@@ -1 +1 @@
1
- {"version":3,"file":"compile.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/compile.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAInC,eAAO,MAAM,cAAc,SAsBxB,CAAA"}
1
+ {"version":3,"file":"compile.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/compile.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAInC,eAAO,MAAM,cAAc,SAgDxB,CAAA"}
@@ -4,32 +4,30 @@ import { compile } from "../../compiler/compile.js";
4
4
  import fs from "node:fs/promises";
5
5
  import { resolve } from "node:path";
6
6
  import { Command } from "commander";
7
- import { paraglideDirectory } from "../main.js";
7
+ import { paraglideDirectory } from "../state.js";
8
8
  import dedent from "dedent";
9
9
  export const compileCommand = new Command()
10
10
  .name("compile")
11
- .summary("Compiles an inlang project into an importable library.")
11
+ .summary("Compiles inlang Paraglide-JS.")
12
12
  .requiredOption("--project <path>", "The path to the project settings file.", "./project.inlang.json")
13
13
  .requiredOption("--namespace <name>", dedent `
14
14
  The import namespace of the compiled library.
15
15
  \nExample: --namespace frontend
16
16
  -> import * as m from "@inlang/paraglide-js/frontend/messages"
17
17
  \n`)
18
- .action((options) => {
19
- runCompileCommand({
20
- projectPath: options.project,
21
- namespace: options.namespace,
22
- paraglideDirectory,
23
- });
24
- });
25
- const runCompileCommand = async (args) => {
26
- consola.info(`Compiling inlang project at "${args.projectPath}".`);
27
- const project = exitIfErrors(await loadProject({ settingsFilePath: resolve(process.cwd(), args.projectPath), nodeishFs: fs }));
18
+ .action(async (options) => {
19
+ consola.info(`Compiling inlang project at "${options.project}".`);
20
+ const path = resolve(process.cwd(), options.project);
21
+ const project = exitIfErrors(await loadProject({
22
+ settingsFilePath: path,
23
+ nodeishFs: fs,
24
+ }));
28
25
  const output = compile({
29
26
  messages: project.query.messages.getAll(),
30
27
  settings: project.settings(),
31
28
  });
32
- const outputDirectory = `${args.paraglideDirectory}/dist/compiled-output` + (args.namespace ? `/${args.namespace}` : "");
29
+ const outputDirectory = `${paraglideDirectory}/dist/compiled-output` +
30
+ (options.namespace ? `/${options.namespace}` : "");
33
31
  for (const [fileName, fileContent] of Object.entries(output)) {
34
32
  // create the compiled-output directory if it doesn't exist
35
33
  await fs.access(outputDirectory).catch(async () => {
@@ -40,17 +38,16 @@ const runCompileCommand = async (args) => {
40
38
  });
41
39
  }
42
40
  consola.success("Successfully compiled the project.");
43
- };
41
+ });
44
42
  /**
45
43
  * Utility function to exit when the project has errors.
46
44
  */
47
45
  const exitIfErrors = (project) => {
48
46
  if (project.errors().length > 0) {
49
- // two console statements for better output formatting
50
- // because project.errors() internal .toString() method
51
- // is better than manual processing.
52
- consola.error(`The project has errors:`);
53
- consola.log(project.errors());
47
+ consola.warn(`The project has errors:`);
48
+ for (const error of project.errors()) {
49
+ consola.error(error);
50
+ }
54
51
  process.exit(1);
55
52
  }
56
53
  return project;
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=compile.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compile.test.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/compile.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,77 @@
1
+ import consola from "consola";
2
+ import { vi, test, expect, beforeEach } from "vitest";
3
+ import memfs from "memfs";
4
+ import mockedFs from "node:fs/promises";
5
+ import fs from "node:fs";
6
+ import { compileCommand } from "./compile.js";
7
+ import { createMessage } from "@inlang/sdk/test-utilities";
8
+ import { resolve } from "node:path";
9
+ import { _setStateForTest } from "../state.js";
10
+ beforeEach(() => {
11
+ vi.resetAllMocks();
12
+ // Re-mock consola before each test call to remove calls from before
13
+ consola.mockTypes(() => vi.fn());
14
+ // set the current working directory to some mock value to prevent
15
+ // the tests from failing when running in a different environment
16
+ process.cwd = () => "/";
17
+ // spy on commonly used functions to prevent console output
18
+ // and allow expecations
19
+ vi.spyOn(consola, "log").mockImplementation(() => undefined);
20
+ vi.spyOn(consola, "info").mockImplementation(() => undefined);
21
+ vi.spyOn(consola, "success").mockImplementation(() => undefined);
22
+ vi.spyOn(consola, "error").mockImplementation(() => undefined);
23
+ vi.spyOn(consola, "warn").mockImplementation(() => undefined);
24
+ vi.spyOn(process, "exit").mockImplementation(() => {
25
+ throw "PROCESS.EXIT()";
26
+ });
27
+ });
28
+ test("it should exit if the project has errors", async () => {
29
+ mockFs({
30
+ "/project.inlang.json": JSON.stringify({
31
+ // invalid source language tag
32
+ sourceLanguageTag: "en-EN-EN",
33
+ languageTags: [],
34
+ modules: [],
35
+ }),
36
+ });
37
+ expect(compileCommand.parseAsync(["--project", "./project.inlang.json", "--namespace", "frontend"])).rejects.toEqual("PROCESS.EXIT()");
38
+ });
39
+ test("it should compile a project with a namespace", async () => {
40
+ const name = "frontend";
41
+ _setStateForTest({ paraglideDirectory: "/node_modules/paraglide-js" });
42
+ const _fs = mockFs({
43
+ "/plugin.js": fs.readFileSync(
44
+ // using the inlang-message-format plugin
45
+ resolve(__dirname, "../../../../../plugins/inlang-message-format/dist/index.js"), { encoding: "utf-8" }),
46
+ "/project.inlang.json": JSON.stringify({
47
+ sourceLanguageTag: "en",
48
+ languageTags: ["de", "en"],
49
+ modules: ["/plugin.js"],
50
+ "plugin.inlang.messageFormat": {
51
+ filePath: "/messages.json",
52
+ },
53
+ }),
54
+ "/messages.json": JSON.stringify({
55
+ $schema: "https://inlang.com/schema/inlang-message-format",
56
+ data: [
57
+ createMessage("loginButton", {
58
+ en: "Login",
59
+ de: "Anmelden",
60
+ }),
61
+ ],
62
+ }),
63
+ });
64
+ await compileCommand.parseAsync(["--project", "./project.inlang.json", "--namespace", name]);
65
+ expect(_fs.existsSync(`/node_modules/paraglide-js/dist/compiled-output/${name}/messages.js`)).toBe(true);
66
+ });
67
+ const mockFs = (files) => {
68
+ const _memfs = memfs.createFsFromVolume(memfs.Volume.fromJSON(files));
69
+ for (const prop in mockedFs) {
70
+ // @ts-ignore - memfs has the same interface as node:fs/promises
71
+ if (typeof mockedFs[prop] !== "function")
72
+ continue;
73
+ // @ts-ignore - memfs has the same interface as node:fs/promises
74
+ vi.spyOn(mockedFs, prop).mockImplementation(_memfs.promises[prop]);
75
+ }
76
+ return _memfs;
77
+ };
@@ -0,0 +1,26 @@
1
+ import { Command } from "commander";
2
+ import { type ProjectSettings } from "@inlang/sdk";
3
+ export declare const initCommand: Command;
4
+ export declare const initializeInlangProject: () => Promise<string>;
5
+ export declare const addParaglideJsToDependencies: () => Promise<void>;
6
+ export declare const promptForNamespace: () => Promise<string>;
7
+ export declare const findExistingInlangProjectPath: () => Promise<string | undefined>;
8
+ export declare const existingProjectFlow: (args: {
9
+ existingProjectPath: string;
10
+ }) => Promise<undefined>;
11
+ export declare const createNewProjectFlow: () => Promise<undefined>;
12
+ export declare const newProjectTemplate: ProjectSettings;
13
+ export declare const checkIfPackageJsonExists: () => Promise<undefined>;
14
+ export declare const checkIfUncommittedChanges: () => Promise<void>;
15
+ export declare const addCompileStepToPackageJSON: (args: {
16
+ projectPath: string;
17
+ namespace: string;
18
+ }) => Promise<undefined>;
19
+ /**
20
+ * Ensures that the moduleResolution compiler option is set to "bundler" or similar in the tsconfig.json.
21
+ *
22
+ * Otherwise, types defined in `package.exports` are not resolved by TypeScript. Leading to type
23
+ * errors with Paraglide-JS.
24
+ */
25
+ export declare const adjustTsConfigIfNecessary: () => Promise<void>;
26
+ //# sourceMappingURL=init.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAGnC,OAAO,EAAe,KAAK,eAAe,EAAE,MAAM,aAAa,CAAA;AAgB/D,eAAO,MAAM,WAAW,SAgBrB,CAAA;AAEH,eAAO,MAAM,uBAAuB,uBAUnC,CAAA;AAED,eAAO,MAAM,4BAA4B,qBAUxC,CAAA;AAED,eAAO,MAAM,kBAAkB,QAAa,QAAQ,MAAM,CAmBzD,CAAA;AAED,eAAO,MAAM,6BAA6B,QAAa,QAAQ,MAAM,GAAG,SAAS,CAYhF,CAAA;AAED,eAAO,MAAM,mBAAmB,SAAgB;IAAE,mBAAmB,EAAE,MAAM,CAAA;CAAE,uBA0B9E,CAAA;AAED,eAAO,MAAM,oBAAoB,0BAkBhC,CAAA;AAED,eAAO,MAAM,kBAAkB,EAAE,eAoBhC,CAAA;AAED,eAAO,MAAM,wBAAwB,0BAOpC,CAAA;AAED,eAAO,MAAM,yBAAyB,qBAyBrC,CAAA;AAED,eAAO,MAAM,2BAA2B,SAAgB;IACvD,WAAW,EAAE,MAAM,CAAA;IACnB,SAAS,EAAE,MAAM,CAAA;CACjB,uBAmCA,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,yBAAyB,qBAqErC,CAAA"}
@@ -0,0 +1,277 @@
1
+ import { Command } from "commander";
2
+ import fs from "node:fs/promises";
3
+ import fsSync from "node:fs";
4
+ import { loadProject } from "@inlang/sdk";
5
+ import consola from "consola";
6
+ import { resolve } from "node:path";
7
+ import { detectJsonFormatting } from "@inlang/detect-json-formatting";
8
+ import JSON5 from "json5";
9
+ import childProcess from "node:child_process";
10
+ import { version } from "../state.js";
11
+ consola.options = {
12
+ ...consola.options,
13
+ // get rid of the date in the logs
14
+ formatOptions: { date: false },
15
+ };
16
+ const DEFAULT_PROJECT_PATH = "./project.inlang.json";
17
+ export const initCommand = new Command()
18
+ .name("init")
19
+ .summary("Initializes inlang Paraglide-JS.")
20
+ .action(async () => {
21
+ consola.box("Welcome to inlang Paraglide-JS 🪂");
22
+ await checkIfUncommittedChanges();
23
+ await checkIfPackageJsonExists();
24
+ const projectPath = await initializeInlangProject();
25
+ const namespace = await promptForNamespace();
26
+ await addCompileStepToPackageJSON({ projectPath, namespace });
27
+ await adjustTsConfigIfNecessary();
28
+ await addParaglideJsToDependencies();
29
+ consola.box("inlang Paraglide-JS has been set up sucessfully.\n\n1. Run your install command (npm i, yarn install, etc)\n2. Run the build script (npm run build, or similar.)\n3. Done :) Happy paragliding 🪂\n\n For questions and feedback, visit https://github.com/inlang/monorepo/discussions.\n");
30
+ });
31
+ export const initializeInlangProject = async () => {
32
+ const existingProjectPath = await findExistingInlangProjectPath();
33
+ if (existingProjectPath) {
34
+ await existingProjectFlow({ existingProjectPath });
35
+ return existingProjectPath;
36
+ }
37
+ else {
38
+ await createNewProjectFlow();
39
+ return DEFAULT_PROJECT_PATH;
40
+ }
41
+ };
42
+ export const addParaglideJsToDependencies = async () => {
43
+ const file = await fs.readFile("./package.json", { encoding: "utf-8" });
44
+ const stringify = detectJsonFormatting(file);
45
+ const pkg = JSON.parse(file);
46
+ if (pkg.dependencies === undefined) {
47
+ pkg.dependencies = {};
48
+ }
49
+ pkg.dependencies["@inlang/paraglide-js"] = version;
50
+ await fs.writeFile("./package.json", stringify(pkg));
51
+ consola.success("Added @inlang/paraglide-js to the dependencies in package.json.");
52
+ };
53
+ export const promptForNamespace = async () => {
54
+ let assumedName = process.cwd().split("/").pop();
55
+ try {
56
+ assumedName = JSON.parse(await fs.readFile("./package.json", { encoding: "utf-8" })).name;
57
+ }
58
+ catch {
59
+ // nothing
60
+ }
61
+ consola.info(`You need to select a name for the project.
62
+
63
+ The name is used to create an importable 'namespace' to distinguish between multiple projects in the same repository. For example, the name \`frontend\` will create the following import statement:
64
+
65
+ \`import * as m from "@inlang/paraglide-js/frontend/messages"\``);
66
+ const namespace = await prompt(`What should be the name of the project?`, {
67
+ type: "text",
68
+ initial: assumedName,
69
+ });
70
+ return namespace.trim();
71
+ };
72
+ export const findExistingInlangProjectPath = async () => {
73
+ for (const path of [
74
+ "./project.inlang.json",
75
+ "../project.inlang.json",
76
+ "../../project.inlang.json",
77
+ ]) {
78
+ if (fsSync.existsSync(path)) {
79
+ return path;
80
+ }
81
+ continue;
82
+ }
83
+ return undefined;
84
+ };
85
+ export const existingProjectFlow = async (args) => {
86
+ const selection = (await prompt(`Do you want to use the inlang project at "${args.existingProjectPath}" or create a new project?`, {
87
+ type: "select",
88
+ options: [
89
+ { label: "Use this project", value: "useExistingProject" },
90
+ { label: "Create a new project", value: "newProject" },
91
+ ],
92
+ })); // the prompt type is incorrect
93
+ if (selection === "newProject") {
94
+ return createNewProjectFlow();
95
+ }
96
+ const project = await loadProject({
97
+ settingsFilePath: resolve(process.cwd(), args.existingProjectPath),
98
+ nodeishFs: fs,
99
+ });
100
+ if (project.errors().length > 0) {
101
+ consola.error("The project contains errors: ");
102
+ for (const error of project.errors()) {
103
+ consola.error(error);
104
+ }
105
+ process.exit(1);
106
+ }
107
+ };
108
+ export const createNewProjectFlow = async () => {
109
+ consola.info(`Creating a new inlang project in the current working directory.`);
110
+ await fs.writeFile(DEFAULT_PROJECT_PATH, JSON.stringify(newProjectTemplate, undefined, 2));
111
+ const project = await loadProject({
112
+ settingsFilePath: resolve(process.cwd(), DEFAULT_PROJECT_PATH),
113
+ nodeishFs: fs,
114
+ });
115
+ if (project.errors().length > 0) {
116
+ consola.warn("Failed to create a new inlang project.\n\nThis is likely an internal bug. Please file an issue at https://github.com/inlang/monorepo.");
117
+ for (const error of project.errors()) {
118
+ consola.error(error);
119
+ }
120
+ return process.exit(1);
121
+ }
122
+ else {
123
+ consola.success("Successfully created a new inlang project.");
124
+ }
125
+ };
126
+ export const newProjectTemplate = {
127
+ $schema: "https://inlang.com/schema/project-settings",
128
+ // defaulting to english to not overwhelm new users
129
+ // with prompts. The user can change this later.
130
+ sourceLanguageTag: "en",
131
+ languageTags: ["en"],
132
+ modules: [
133
+ // for instant gratification, we're adding the most common rules
134
+ "https://cdn.jsdelivr.net/npm/@inlang/message-lint-rule-empty-pattern@latest/dist/index.js",
135
+ "https://cdn.jsdelivr.net/npm/@inlang/message-lint-rule-identical-pattern@latest/dist/index.js",
136
+ "https://cdn.jsdelivr.net/npm/@inlang/message-lint-rule-missing-translation@latest/dist/index.js",
137
+ "https://cdn.jsdelivr.net/npm/@inlang/message-lint-rule-without-source@latest/dist/index.js",
138
+ // default to the message format plugin because it supports all features
139
+ "https://cdn.jsdelivr.net/npm/@inlang/plugin-message-format@latest/dist/index.js",
140
+ ],
141
+ "plugin.inlang.messageFormat": {
142
+ // using .inlang/paraglide-js as directory to avoid future conflicts when an official .inlang
143
+ // directory is introduced, see https://github.com/inlang/monorepo/discussions/1418
144
+ filePath: "./.inlang/plugin.inlang.messageFormat/messages.json",
145
+ },
146
+ };
147
+ export const checkIfPackageJsonExists = async () => {
148
+ if (fsSync.existsSync("./package.json") === false) {
149
+ consola.warn("No package.json found in the current working directory. Please change the working directory to the directory with a package.json file.");
150
+ return process.exit(0);
151
+ }
152
+ };
153
+ export const checkIfUncommittedChanges = async () => {
154
+ try {
155
+ if (childProcess.execSync("git status --porcelain").toString().length === 0) {
156
+ return;
157
+ }
158
+ consola.info(`You have uncommitted changes.\n\nPlease commit your changes before initializing inlang Paraglide-JS. Committing outstanding changes ensures that you don't lose any work, and see the changes the paraglide-js init command introduces.`);
159
+ const response = await prompt("Do you want to initialize inlang Paraglide-JS without committing your current changes?", {
160
+ type: "confirm",
161
+ initial: false,
162
+ });
163
+ if (response === true) {
164
+ return;
165
+ }
166
+ else {
167
+ process.exit(0);
168
+ }
169
+ }
170
+ catch (e) {
171
+ // git cli is not installed
172
+ return;
173
+ }
174
+ };
175
+ export const addCompileStepToPackageJSON = async (args) => {
176
+ const file = await fs.readFile("./package.json", { encoding: "utf-8" });
177
+ const stringify = detectJsonFormatting(file);
178
+ const pkg = JSON.parse(file);
179
+ if (pkg?.scripts?.build === undefined) {
180
+ if (pkg.scripts === undefined) {
181
+ pkg.scripts = {};
182
+ }
183
+ pkg.scripts.build = `paraglide-js compile --project ${args.projectPath} --namespace ${args.namespace}`;
184
+ }
185
+ else if (pkg?.scripts?.build.includes("paraglide-js compile") === false) {
186
+ pkg.scripts.build = `paraglide-js compile --project ${args.projectPath} --namespace ${args.namespace} && ${pkg.scripts.build}`;
187
+ }
188
+ else {
189
+ consola.warn(`The "build" script in the \`package.json\` already contains a "paraglide-js compile" command.
190
+
191
+ Please add the following command to your build script manually:
192
+
193
+ \`paraglide-js compile --project ${args.projectPath} --namespace ${args.namespace}\``);
194
+ const response = await consola.prompt("Have you added the compile command to your build script?", {
195
+ type: "confirm",
196
+ initial: false,
197
+ });
198
+ if (response === false) {
199
+ consola.log("Please remove the paraglide-js compile command from your build script and try again.");
200
+ return process.exit(0);
201
+ }
202
+ else {
203
+ return;
204
+ }
205
+ }
206
+ await fs.writeFile("./package.json", stringify(pkg));
207
+ consola.success("Successfully added the compile command to the build step in package.json.");
208
+ };
209
+ /**
210
+ * Ensures that the moduleResolution compiler option is set to "bundler" or similar in the tsconfig.json.
211
+ *
212
+ * Otherwise, types defined in `package.exports` are not resolved by TypeScript. Leading to type
213
+ * errors with Paraglide-JS.
214
+ */
215
+ export const adjustTsConfigIfNecessary = async () => {
216
+ if (fsSync.existsSync("./tsconfig.json") === false) {
217
+ return;
218
+ }
219
+ const file = await fs.readFile("./tsconfig.json", { encoding: "utf-8" });
220
+ // tsconfig allows comments ... FML
221
+ const tsconfig = JSON5.parse(file);
222
+ let parentTsConfig;
223
+ if (tsconfig.extends) {
224
+ try {
225
+ const parentTsConfigPath = resolve(process.cwd(), tsconfig.extends);
226
+ const parentTsConfigFile = await fs.readFile(parentTsConfigPath, { encoding: "utf-8" });
227
+ parentTsConfig = JSON5.parse(parentTsConfigFile);
228
+ }
229
+ catch {
230
+ consola.warn(`The tsconfig.json is extended from a tsconfig that couldn't be read. Maybe the file doesn't exist yet or is a NPM package. Continuing without taking the extended from tsconfig into consideration.`);
231
+ }
232
+ }
233
+ // options that don't support package.exports
234
+ const invalidOptions = ["classic", "node", "node10"];
235
+ const moduleResolution = tsconfig.compilerOptions?.moduleResolution ?? parentTsConfig?.compilerOptions?.moduleResolution;
236
+ if (moduleResolution && invalidOptions.includes(moduleResolution.toLowerCase()) === false) {
237
+ // the moduleResolution is already set to bundler or similar
238
+ return;
239
+ }
240
+ consola.info(`You need to set the \`compilerOptions.moduleResolution\` to "Bundler" in the \`tsconfig.json\` file:
241
+
242
+ \`{
243
+ "compilerOptions": {
244
+ "moduleResolution": "Bundler"
245
+ }
246
+ }\``);
247
+ let isValid = false;
248
+ while (isValid === false) {
249
+ const response = await prompt(`Did you set the \`compilerOptions.moduleResolution\` to "Bundler"?`, {
250
+ type: "confirm",
251
+ initial: false,
252
+ });
253
+ if (response === false) {
254
+ return consola.warn("Continuing without adjusting the tsconfig.json. This may lead to type errors.");
255
+ }
256
+ const file = await fs.readFile("./tsconfig.json", { encoding: "utf-8" });
257
+ const tsconfig = JSON5.parse(file);
258
+ if (tsconfig?.compilerOptions?.moduleResolution &&
259
+ tsconfig.compilerOptions.moduleResolution.toLowerCase() === "bundler") {
260
+ isValid = true;
261
+ return;
262
+ }
263
+ else {
264
+ consola.error("The compiler options have not been adjusted. Please set the `compilerOptions.moduleResolution` to `Bundler`.");
265
+ }
266
+ }
267
+ };
268
+ /**
269
+ * Wrapper to exit the process if the user presses CTRL+C.
270
+ */
271
+ const prompt = async (message, options) => {
272
+ const response = await consola.prompt(message, options);
273
+ if (response?.toString() === "Symbol(clack:cancel)") {
274
+ process.exit(0);
275
+ }
276
+ return response;
277
+ };
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=init.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.test.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/init.test.ts"],"names":[],"mappings":""}