@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.
- package/README.md +10 -2
- package/dist/cli/commands/compile.d.ts.map +1 -1
- package/dist/cli/commands/compile.js +16 -19
- package/dist/cli/commands/compile.test.d.ts +2 -0
- package/dist/cli/commands/compile.test.d.ts.map +1 -0
- package/dist/cli/commands/compile.test.js +77 -0
- package/dist/cli/commands/init.d.ts +26 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/init.js +277 -0
- package/dist/cli/commands/init.test.d.ts +2 -0
- package/dist/cli/commands/init.test.d.ts.map +1 -0
- package/dist/cli/commands/init.test.js +472 -0
- package/dist/cli/main.d.ts +0 -8
- package/dist/cli/main.d.ts.map +1 -1
- package/dist/cli/main.js +12 -21
- package/dist/cli/main.test.d.ts +2 -0
- package/dist/cli/main.test.d.ts.map +1 -0
- package/dist/cli/main.test.js +37 -0
- package/dist/cli/state.d.ts +14 -0
- package/dist/cli/state.d.ts.map +1 -0
- package/dist/cli/state.js +28 -0
- package/dist/compiled-output/website/messages.d.ts +73 -0
- package/dist/compiled-output/website/messages.js +1543 -0
- package/dist/compiled-output/{sveltekit-example → website}/runtime.d.ts +1 -1
- package/dist/compiled-output/{react-example → website}/runtime.js +1 -1
- package/package.json +4 -1
- package/dist/compiled-output/example-javascript/messages.d.ts +0 -7
- package/dist/compiled-output/example-javascript/messages.js +0 -42
- package/dist/compiled-output/example-javascript/runtime.d.ts +0 -38
- package/dist/compiled-output/example-javascript/runtime.js +0 -112
- package/dist/compiled-output/react-example/messages.d.ts +0 -7
- package/dist/compiled-output/react-example/messages.js +0 -42
- package/dist/compiled-output/react-example/runtime.d.ts +0 -38
- package/dist/compiled-output/sveltekit-example/messages.d.ts +0 -7
- package/dist/compiled-output/sveltekit-example/messages.js +0 -42
- package/dist/compiled-output/sveltekit-example/runtime.js +0 -112
- package/dist/compiler/jsdocFromParams.d.ts +0 -12
- package/dist/compiler/jsdocFromParams.d.ts.map +0 -1
- package/dist/compiler/jsdocFromParams.js +0 -17
- package/dist/compiler/jsdocFromParams.test.d.ts +0 -2
- package/dist/compiler/jsdocFromParams.test.d.ts.map +0 -1
- 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 <
|
|
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,
|
|
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 "../
|
|
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
|
|
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
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
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 = `${
|
|
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
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
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 @@
|
|
|
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 @@
|
|
|
1
|
+
{"version":3,"file":"init.test.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/init.test.ts"],"names":[],"mappings":""}
|