@inlang/sdk 0.17.0 → 0.19.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.
- package/dist/adapter/solidAdapter.test.js +16 -15
- package/dist/createNodeishFsWithAbsolutePaths.d.ts +2 -2
- package/dist/createNodeishFsWithAbsolutePaths.d.ts.map +1 -1
- package/dist/createNodeishFsWithAbsolutePaths.js +5 -4
- package/dist/createNodeishFsWithAbsolutePaths.test.js +5 -4
- package/dist/createNodeishFsWithWatcher.d.ts +12 -0
- package/dist/createNodeishFsWithWatcher.d.ts.map +1 -0
- package/dist/createNodeishFsWithWatcher.js +52 -0
- package/dist/createNodeishFsWithWatcher.test.d.ts +2 -0
- package/dist/createNodeishFsWithWatcher.test.d.ts.map +1 -0
- package/dist/createNodeishFsWithWatcher.test.js +32 -0
- package/dist/isAbsolutePath.test.js +1 -1
- package/dist/loadProject.d.ts +4 -4
- package/dist/loadProject.d.ts.map +1 -1
- package/dist/loadProject.js +45 -24
- package/dist/loadProject.test.js +175 -74
- package/dist/migrations/migrateToDirectory.d.ts +10 -0
- package/dist/migrations/migrateToDirectory.d.ts.map +1 -0
- package/dist/migrations/migrateToDirectory.js +46 -0
- package/dist/migrations/migrateToDirectory.test.d.ts +2 -0
- package/dist/migrations/migrateToDirectory.test.d.ts.map +1 -0
- package/dist/migrations/migrateToDirectory.test.js +48 -0
- package/dist/resolve-modules/plugins/resolvePlugins.js +1 -1
- package/dist/resolve-modules/plugins/resolvePlugins.test.js +2 -1
- package/dist/resolve-modules/plugins/types.d.ts +2 -1
- package/dist/resolve-modules/plugins/types.d.ts.map +1 -1
- package/dist/resolve-modules/validateModuleSettings.test.js +1 -1
- package/package.json +56 -56
- package/src/adapter/solidAdapter.test.ts +16 -15
- package/src/createNodeishFsWithAbsolutePaths.test.ts +5 -4
- package/src/createNodeishFsWithAbsolutePaths.ts +9 -5
- package/src/createNodeishFsWithWatcher.test.ts +40 -0
- package/src/createNodeishFsWithWatcher.ts +58 -0
- package/src/isAbsolutePath.test.ts +1 -1
- package/src/loadProject.test.ts +206 -75
- package/src/loadProject.ts +61 -31
- package/src/migrations/migrateToDirectory.test.ts +54 -0
- package/src/migrations/migrateToDirectory.ts +59 -0
- package/src/resolve-modules/plugins/resolvePlugins.test.ts +2 -1
- package/src/resolve-modules/plugins/resolvePlugins.ts +1 -1
- package/src/resolve-modules/plugins/types.ts +5 -2
- package/src/resolve-modules/validateModuleSettings.test.ts +1 -1
|
@@ -72,10 +72,10 @@ const $import = async (name) => ({
|
|
|
72
72
|
describe("config", () => {
|
|
73
73
|
it("should react to changes in config", async () => {
|
|
74
74
|
const fs = createNodeishMemoryFs();
|
|
75
|
-
await fs.mkdir("/user/project", { recursive: true });
|
|
76
|
-
await fs.writeFile("/user/project
|
|
75
|
+
await fs.mkdir("/user/project.inlang", { recursive: true });
|
|
76
|
+
await fs.writeFile("/user/project.inlang/settings.json", JSON.stringify(config));
|
|
77
77
|
const project = solidAdapter(await loadProject({
|
|
78
|
-
|
|
78
|
+
projectPath: "/user/project.inlang",
|
|
79
79
|
nodeishFs: fs,
|
|
80
80
|
_import: $import,
|
|
81
81
|
}), { from });
|
|
@@ -96,10 +96,10 @@ describe("config", () => {
|
|
|
96
96
|
describe("installed", () => {
|
|
97
97
|
it("react to changes that are unrelated to installed items", async () => {
|
|
98
98
|
const fs = createNodeishMemoryFs();
|
|
99
|
-
await fs.mkdir("/user/project", { recursive: true });
|
|
100
|
-
await fs.writeFile("/user/project
|
|
99
|
+
await fs.mkdir("/user/project.inlang", { recursive: true });
|
|
100
|
+
await fs.writeFile("/user/project.inlang/settings.json", JSON.stringify(config));
|
|
101
101
|
const project = solidAdapter(await loadProject({
|
|
102
|
-
|
|
102
|
+
projectPath: "/user/project.inlang",
|
|
103
103
|
nodeishFs: fs,
|
|
104
104
|
_import: $import,
|
|
105
105
|
}), { from });
|
|
@@ -149,10 +149,10 @@ describe("messages", () => {
|
|
|
149
149
|
saveMessages: () => undefined,
|
|
150
150
|
};
|
|
151
151
|
const mockImport = async () => ({ default: mockPlugin });
|
|
152
|
-
await fs.mkdir("/user/project", { recursive: true });
|
|
153
|
-
await fs.writeFile("/user/project
|
|
152
|
+
await fs.mkdir("/user/project.inlang.inlang", { recursive: true });
|
|
153
|
+
await fs.writeFile("/user/project.inlang.inlang/settings.json", JSON.stringify(mockConfig));
|
|
154
154
|
const project = solidAdapter(await loadProject({
|
|
155
|
-
|
|
155
|
+
projectPath: "/user/project.inlang.inlang",
|
|
156
156
|
nodeishFs: fs,
|
|
157
157
|
_import: mockImport,
|
|
158
158
|
}), { from });
|
|
@@ -170,10 +170,10 @@ describe("messages", () => {
|
|
|
170
170
|
});
|
|
171
171
|
it("should react to changes in messages", async () => {
|
|
172
172
|
const fs = createNodeishMemoryFs();
|
|
173
|
-
await fs.mkdir("/user/project", { recursive: true });
|
|
174
|
-
await fs.writeFile("/user/project
|
|
173
|
+
await fs.mkdir("/user/project.inlang.inlang", { recursive: true });
|
|
174
|
+
await fs.writeFile("/user/project.inlang.inlang/settings.json", JSON.stringify(config));
|
|
175
175
|
const project = solidAdapter(await loadProject({
|
|
176
|
-
|
|
176
|
+
projectPath: "/user/project.inlang.inlang",
|
|
177
177
|
nodeishFs: fs,
|
|
178
178
|
_import: $import,
|
|
179
179
|
}), { from });
|
|
@@ -216,9 +216,10 @@ describe("lint", () => {
|
|
|
216
216
|
it.todo("should react to changes in config", async () => {
|
|
217
217
|
await createRoot(async () => {
|
|
218
218
|
const fs = createNodeishMemoryFs();
|
|
219
|
-
await fs.
|
|
219
|
+
await fs.mkdir("./project.inlang", { recursive: true });
|
|
220
|
+
await fs.writeFile("./project.inlang/settings.json", JSON.stringify(config));
|
|
220
221
|
const project = solidAdapter(await loadProject({
|
|
221
|
-
|
|
222
|
+
projectPath: "./project.inlang",
|
|
222
223
|
nodeishFs: fs,
|
|
223
224
|
_import: $import,
|
|
224
225
|
}), { from });
|
|
@@ -245,7 +246,7 @@ describe("lint", () => {
|
|
|
245
246
|
const fs = createNodeishMemoryFs();
|
|
246
247
|
await fs.writeFile("./project.config.json", JSON.stringify(config));
|
|
247
248
|
const project = solidAdapter(await loadProject({
|
|
248
|
-
|
|
249
|
+
projectPath: "./project.config.json",
|
|
249
250
|
nodeishFs: fs,
|
|
250
251
|
_import: $import,
|
|
251
252
|
}), { from });
|
|
@@ -3,10 +3,10 @@ import type { NodeishFilesystemSubset } from "@inlang/plugin";
|
|
|
3
3
|
* Wraps the nodeish filesystem subset with a function that intercepts paths
|
|
4
4
|
* and prepends the base path.
|
|
5
5
|
*
|
|
6
|
-
* The paths are resolved from the `
|
|
6
|
+
* The paths are resolved from the `projectPath` argument.
|
|
7
7
|
*/
|
|
8
8
|
export declare const createNodeishFsWithAbsolutePaths: (args: {
|
|
9
|
-
|
|
9
|
+
projectPath: string;
|
|
10
10
|
nodeishFs: NodeishFilesystemSubset;
|
|
11
11
|
}) => NodeishFilesystemSubset;
|
|
12
12
|
//# sourceMappingURL=createNodeishFsWithAbsolutePaths.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createNodeishFsWithAbsolutePaths.d.ts","sourceRoot":"","sources":["../src/createNodeishFsWithAbsolutePaths.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAA;AAI7D;;;;;GAKG;AACH,eAAO,MAAM,gCAAgC,SAAU;IACtD,
|
|
1
|
+
{"version":3,"file":"createNodeishFsWithAbsolutePaths.d.ts","sourceRoot":"","sources":["../src/createNodeishFsWithAbsolutePaths.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAA;AAI7D;;;;;GAKG;AACH,eAAO,MAAM,gCAAgC,SAAU;IACtD,WAAW,EAAE,MAAM,CAAA;IACnB,SAAS,EAAE,uBAAuB,CAAA;CAClC,KAAG,uBA6BH,CAAA"}
|
|
@@ -4,15 +4,15 @@ import { isAbsolutePath } from "./isAbsolutePath.js";
|
|
|
4
4
|
* Wraps the nodeish filesystem subset with a function that intercepts paths
|
|
5
5
|
* and prepends the base path.
|
|
6
6
|
*
|
|
7
|
-
* The paths are resolved from the `
|
|
7
|
+
* The paths are resolved from the `projectPath` argument.
|
|
8
8
|
*/
|
|
9
9
|
export const createNodeishFsWithAbsolutePaths = (args) => {
|
|
10
|
-
if (!isAbsolutePath(args.
|
|
11
|
-
throw new Error(`Expected an absolute path but received "${args.
|
|
10
|
+
if (!isAbsolutePath(args.projectPath)) {
|
|
11
|
+
throw new Error(`Expected an absolute path but received "${args.projectPath}".`);
|
|
12
12
|
}
|
|
13
13
|
// get the base path of the settings file by
|
|
14
14
|
// removing the file name from the path
|
|
15
|
-
const basePath = normalizePath(args.
|
|
15
|
+
const basePath = normalizePath(args.projectPath).split("/").slice(0, -1).join("/");
|
|
16
16
|
const makeAbsolute = (path) => {
|
|
17
17
|
if (isAbsolutePath(path)) {
|
|
18
18
|
return normalizePath(path);
|
|
@@ -25,5 +25,6 @@ export const createNodeishFsWithAbsolutePaths = (args) => {
|
|
|
25
25
|
readdir: (path) => args.nodeishFs.readdir(makeAbsolute(path)),
|
|
26
26
|
mkdir: (path) => args.nodeishFs.mkdir(makeAbsolute(path)),
|
|
27
27
|
writeFile: (path, data) => args.nodeishFs.writeFile(makeAbsolute(path), data),
|
|
28
|
+
watch: (path, options) => args.nodeishFs.watch(makeAbsolute(path), options),
|
|
28
29
|
};
|
|
29
30
|
};
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { it, expect, vi } from "vitest";
|
|
2
2
|
import { createNodeishFsWithAbsolutePaths } from "./createNodeishFsWithAbsolutePaths.js";
|
|
3
|
-
it("throws an error if
|
|
3
|
+
it("throws an error if projectPath is not an absolute path", () => {
|
|
4
4
|
const relativePath = "relative/path";
|
|
5
|
-
expect(() => createNodeishFsWithAbsolutePaths({
|
|
5
|
+
expect(() => createNodeishFsWithAbsolutePaths({ projectPath: relativePath, nodeishFs: {} })).toThrow();
|
|
6
6
|
});
|
|
7
7
|
it("intercepts paths correctly for readFile", async () => {
|
|
8
|
-
const
|
|
8
|
+
const projectPath = `/Users/samuel/Documents/paraglide/example/project.inlang`;
|
|
9
9
|
const filePaths = [
|
|
10
10
|
["file.txt", `/Users/samuel/Documents/paraglide/example/file.txt`],
|
|
11
11
|
["./file.txt", `/Users/samuel/Documents/paraglide/example/file.txt`],
|
|
@@ -20,9 +20,10 @@ it("intercepts paths correctly for readFile", async () => {
|
|
|
20
20
|
readdir: vi.fn(),
|
|
21
21
|
mkdir: vi.fn(),
|
|
22
22
|
writeFile: vi.fn(),
|
|
23
|
+
watch: vi.fn(),
|
|
23
24
|
};
|
|
24
25
|
const interceptedFs = createNodeishFsWithAbsolutePaths({
|
|
25
|
-
|
|
26
|
+
projectPath,
|
|
26
27
|
nodeishFs: mockNodeishFs,
|
|
27
28
|
});
|
|
28
29
|
for (const [path, expectedPath] of filePaths) {
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { NodeishFilesystemSubset } from "@inlang/plugin";
|
|
2
|
+
/**
|
|
3
|
+
* Wraps the nodeish filesystem subset with a function that intercepts paths
|
|
4
|
+
* and prepends the base path.
|
|
5
|
+
*
|
|
6
|
+
* The paths are resolved from the `projectPath` argument.
|
|
7
|
+
*/
|
|
8
|
+
export declare const createNodeishFsWithWatcher: (args: {
|
|
9
|
+
nodeishFs: NodeishFilesystemSubset;
|
|
10
|
+
updateMessages: () => void;
|
|
11
|
+
}) => NodeishFilesystemSubset;
|
|
12
|
+
//# sourceMappingURL=createNodeishFsWithWatcher.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createNodeishFsWithWatcher.d.ts","sourceRoot":"","sources":["../src/createNodeishFsWithWatcher.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAA;AAE7D;;;;;GAKG;AACH,eAAO,MAAM,0BAA0B,SAAU;IAChD,SAAS,EAAE,uBAAuB,CAAA;IAClC,cAAc,EAAE,MAAM,IAAI,CAAA;CAC1B,KAAG,uBA8CH,CAAA"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wraps the nodeish filesystem subset with a function that intercepts paths
|
|
3
|
+
* and prepends the base path.
|
|
4
|
+
*
|
|
5
|
+
* The paths are resolved from the `projectPath` argument.
|
|
6
|
+
*/
|
|
7
|
+
export const createNodeishFsWithWatcher = (args) => {
|
|
8
|
+
const pathList = [];
|
|
9
|
+
const makeWatcher = (path) => {
|
|
10
|
+
const abortController = new AbortController();
|
|
11
|
+
(async () => {
|
|
12
|
+
try {
|
|
13
|
+
const watcher = args.nodeishFs.watch(path, {
|
|
14
|
+
signal: abortController.signal,
|
|
15
|
+
persistent: false,
|
|
16
|
+
});
|
|
17
|
+
if (watcher) {
|
|
18
|
+
//eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
19
|
+
for await (const event of watcher) {
|
|
20
|
+
args.updateMessages();
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
catch (err) {
|
|
25
|
+
if (err.name === "AbortError")
|
|
26
|
+
return;
|
|
27
|
+
// https://github.com/inlang/monorepo/issues/1647
|
|
28
|
+
// the file does not exist (yet)
|
|
29
|
+
// this is not testable beacause the fs.watch api differs
|
|
30
|
+
// from node and lix. lenghty
|
|
31
|
+
else if (err.code === "ENOENT")
|
|
32
|
+
return;
|
|
33
|
+
throw err;
|
|
34
|
+
}
|
|
35
|
+
})();
|
|
36
|
+
};
|
|
37
|
+
const readFileAndExtractPath = (path, options) => {
|
|
38
|
+
if (!pathList.includes(path)) {
|
|
39
|
+
makeWatcher(path);
|
|
40
|
+
pathList.push(path);
|
|
41
|
+
}
|
|
42
|
+
return args.nodeishFs.readFile(path, options);
|
|
43
|
+
};
|
|
44
|
+
return {
|
|
45
|
+
// @ts-expect-error
|
|
46
|
+
readFile: (path, options) => readFileAndExtractPath(path, options),
|
|
47
|
+
readdir: args.nodeishFs.readdir,
|
|
48
|
+
mkdir: args.nodeishFs.mkdir,
|
|
49
|
+
writeFile: args.nodeishFs.writeFile,
|
|
50
|
+
watch: args.nodeishFs.watch,
|
|
51
|
+
};
|
|
52
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createNodeishFsWithWatcher.test.d.ts","sourceRoot":"","sources":["../src/createNodeishFsWithWatcher.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { createNodeishMemoryFs } from "@lix-js/fs";
|
|
2
|
+
import { describe, it, expect } from "vitest";
|
|
3
|
+
import { createNodeishFsWithWatcher } from "./createNodeishFsWithWatcher.js";
|
|
4
|
+
describe("watcher", () => {
|
|
5
|
+
it("should trigger the update function when file changes", async () => {
|
|
6
|
+
let counter = 0;
|
|
7
|
+
const fs = createNodeishFsWithWatcher({
|
|
8
|
+
nodeishFs: createNodeishMemoryFs(),
|
|
9
|
+
updateMessages: () => {
|
|
10
|
+
counter++;
|
|
11
|
+
},
|
|
12
|
+
});
|
|
13
|
+
// establish watcher
|
|
14
|
+
await fs.writeFile("file.txt", "a");
|
|
15
|
+
await fs.readFile("file.txt", { encoding: "utf-8" });
|
|
16
|
+
expect(counter).toBe(0);
|
|
17
|
+
// initial file change
|
|
18
|
+
await fs.writeFile("file.txt", "b");
|
|
19
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
20
|
+
expect(counter).toBe(1);
|
|
21
|
+
// change file
|
|
22
|
+
await fs.writeFile("file.txt", "a");
|
|
23
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
24
|
+
//check if update function was called
|
|
25
|
+
expect(counter).toBe(2);
|
|
26
|
+
// change file
|
|
27
|
+
await fs.readFile("file.txt");
|
|
28
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
29
|
+
//check if update function was called
|
|
30
|
+
expect(counter).toBe(2);
|
|
31
|
+
});
|
|
32
|
+
});
|
|
@@ -8,7 +8,7 @@ describe("isAbsolutePath", () => {
|
|
|
8
8
|
});
|
|
9
9
|
it("should correctly identify Windows absolute paths", () => {
|
|
10
10
|
assert.isTrue(isAbsolutePath("C:\\Users\\User\\Documents\\File.txt"));
|
|
11
|
-
assert.isTrue(isAbsolutePath("C:/Users/user/project
|
|
11
|
+
assert.isTrue(isAbsolutePath("C:/Users/user/project.inlang/settings.json"));
|
|
12
12
|
assert.isFalse(isAbsolutePath("Projects\\Project1\\source\\file.txt"));
|
|
13
13
|
});
|
|
14
14
|
it("should handle edge cases", () => {
|
package/dist/loadProject.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import type { InlangProject, Subscribable } from "./api.js";
|
|
2
2
|
import { type ImportFunction } from "./resolve-modules/index.js";
|
|
3
|
-
import { type
|
|
3
|
+
import { type NodeishFilesystem } from "@lix-js/fs";
|
|
4
4
|
/**
|
|
5
5
|
* Creates an inlang instance.
|
|
6
6
|
*
|
|
7
|
-
* @param
|
|
7
|
+
* @param projectPath - Absolute path to the inlang settings file.
|
|
8
8
|
* @param nodeishFs - Filesystem that implements the NodeishFilesystemSubset interface.
|
|
9
9
|
* @param _import - Use `_import` to pass a custom import function for testing,
|
|
10
10
|
* and supporting legacy resolvedModules such as CJS.
|
|
@@ -12,8 +12,8 @@ import { type NodeishFilesystemSubset } from "./versionedInterfaces.js";
|
|
|
12
12
|
*
|
|
13
13
|
*/
|
|
14
14
|
export declare const loadProject: (args: {
|
|
15
|
-
|
|
16
|
-
nodeishFs:
|
|
15
|
+
projectPath: string;
|
|
16
|
+
nodeishFs: NodeishFilesystem;
|
|
17
17
|
_import?: ImportFunction | undefined;
|
|
18
18
|
_capture?: ((id: string, props: Record<string, unknown>) => void) | undefined;
|
|
19
19
|
}) => Promise<InlangProject>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loadProject.d.ts","sourceRoot":"","sources":["../src/loadProject.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACX,aAAa,EAGb,YAAY,EACZ,MAAM,UAAU,CAAA;AACjB,OAAO,EAAE,KAAK,cAAc,EAAkB,MAAM,4BAA4B,CAAA;
|
|
1
|
+
{"version":3,"file":"loadProject.d.ts","sourceRoot":"","sources":["../src/loadProject.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACX,aAAa,EAGb,YAAY,EACZ,MAAM,UAAU,CAAA;AACjB,OAAO,EAAE,KAAK,cAAc,EAAkB,MAAM,4BAA4B,CAAA;AAkBhF,OAAO,EAAiB,KAAK,iBAAiB,EAAE,MAAM,YAAY,CAAA;AAOlE;;;;;;;;;GASG;AACH,eAAO,MAAM,WAAW;iBACV,MAAM;eACR,iBAAiB;;qBAEZ,MAAM,SAAS,OAAO,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI;MAC5D,QAAQ,aAAa,CAkOxB,CAAA;AAwHD,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,YAAY,CAAC,CAAC,CAAC,CAQtE"}
|
package/dist/loadProject.js
CHANGED
|
@@ -11,11 +11,13 @@ import { migrateIfOutdated } from "@inlang/project-settings/migration";
|
|
|
11
11
|
import { createNodeishFsWithAbsolutePaths } from "./createNodeishFsWithAbsolutePaths.js";
|
|
12
12
|
import { normalizePath } from "@lix-js/fs";
|
|
13
13
|
import { isAbsolutePath } from "./isAbsolutePath.js";
|
|
14
|
+
import { createNodeishFsWithWatcher } from "./createNodeishFsWithWatcher.js";
|
|
15
|
+
import { maybeMigrateToDirectory } from "./migrations/migrateToDirectory.js";
|
|
14
16
|
const settingsCompiler = TypeCompiler.Compile(ProjectSettings);
|
|
15
17
|
/**
|
|
16
18
|
* Creates an inlang instance.
|
|
17
19
|
*
|
|
18
|
-
* @param
|
|
20
|
+
* @param projectPath - Absolute path to the inlang settings file.
|
|
19
21
|
* @param nodeishFs - Filesystem that implements the NodeishFilesystemSubset interface.
|
|
20
22
|
* @param _import - Use `_import` to pass a custom import function for testing,
|
|
21
23
|
* and supporting legacy resolvedModules such as CJS.
|
|
@@ -23,25 +25,30 @@ const settingsCompiler = TypeCompiler.Compile(ProjectSettings);
|
|
|
23
25
|
*
|
|
24
26
|
*/
|
|
25
27
|
export const loadProject = async (args) => {
|
|
28
|
+
const projectPath = normalizePath(args.projectPath);
|
|
29
|
+
// -- migrate if outdated ------------------------------------------------
|
|
30
|
+
await maybeMigrateToDirectory({ nodeishFs: args.nodeishFs, projectPath });
|
|
26
31
|
// -- validation --------------------------------------------------------
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
if (!isAbsolutePath(args.
|
|
31
|
-
throw new LoadProjectInvalidArgument(`Expected an absolute path but received "${args.
|
|
32
|
+
// the only place where throwing is acceptable because the project
|
|
33
|
+
// won't even be loaded. do not throw anywhere else. otherwise, apps
|
|
34
|
+
// can't handle errors gracefully.
|
|
35
|
+
if (!isAbsolutePath(args.projectPath)) {
|
|
36
|
+
throw new LoadProjectInvalidArgument(`Expected an absolute path but received "${args.projectPath}".`, { argument: "projectPath" });
|
|
37
|
+
}
|
|
38
|
+
else if (/[^\\/]+\.inlang$/.test(projectPath) === false) {
|
|
39
|
+
throw new LoadProjectInvalidArgument(`Expected a path ending in "{name}.inlang" but received "${projectPath}".\n\nValid examples: \n- "/path/to/micky-mouse.inlang"\n- "/path/to/green-elephant.inlang\n`, { argument: "projectPath" });
|
|
32
40
|
}
|
|
33
|
-
const settingsFilePath = normalizePath(args.settingsFilePath);
|
|
34
41
|
// -- load project ------------------------------------------------------
|
|
35
42
|
return await createRoot(async () => {
|
|
36
43
|
const [initialized, markInitAsComplete, markInitAsFailed] = createAwaitable();
|
|
37
44
|
const nodeishFs = createNodeishFsWithAbsolutePaths({
|
|
38
|
-
|
|
45
|
+
projectPath,
|
|
39
46
|
nodeishFs: args.nodeishFs,
|
|
40
47
|
});
|
|
41
48
|
// -- settings ------------------------------------------------------------
|
|
42
49
|
const [settings, _setSettings] = createSignal();
|
|
43
50
|
createEffect(() => {
|
|
44
|
-
loadSettings({ settingsFilePath, nodeishFs })
|
|
51
|
+
loadSettings({ settingsFilePath: projectPath + "/settings.json", nodeishFs })
|
|
45
52
|
.then((settings) => {
|
|
46
53
|
setSettings(settings);
|
|
47
54
|
// rename settings to get a convenient access to the data in Posthog
|
|
@@ -53,7 +60,7 @@ export const loadProject = async (args) => {
|
|
|
53
60
|
});
|
|
54
61
|
});
|
|
55
62
|
// TODO: create FS watcher and update settings on change
|
|
56
|
-
const writeSettingsToDisk = skipFirst((settings) => _writeSettingsToDisk({ nodeishFs, settings }));
|
|
63
|
+
const writeSettingsToDisk = skipFirst((settings) => _writeSettingsToDisk({ nodeishFs, settings, projectPath }));
|
|
57
64
|
const setSettings = (settings) => {
|
|
58
65
|
try {
|
|
59
66
|
const validatedSettings = parseSettings(settings);
|
|
@@ -95,14 +102,24 @@ export const loadProject = async (args) => {
|
|
|
95
102
|
markInitAsFailed(undefined);
|
|
96
103
|
return;
|
|
97
104
|
}
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
105
|
+
const loadAndSetMessages = async (fs) => {
|
|
106
|
+
makeTrulyAsync(_resolvedModules.resolvedPluginApi.loadMessages({
|
|
107
|
+
settings: settingsValue,
|
|
108
|
+
nodeishFs: fs,
|
|
109
|
+
}))
|
|
110
|
+
.then((messages) => {
|
|
111
|
+
setMessages(messages);
|
|
112
|
+
markInitAsComplete();
|
|
113
|
+
})
|
|
114
|
+
.catch((err) => markInitAsFailed(new PluginLoadMessagesError({ cause: err })));
|
|
115
|
+
};
|
|
116
|
+
const fsWithWatcher = createNodeishFsWithWatcher({
|
|
117
|
+
nodeishFs: nodeishFs,
|
|
118
|
+
updateMessages: () => {
|
|
119
|
+
loadAndSetMessages(nodeishFs);
|
|
120
|
+
},
|
|
121
|
+
});
|
|
122
|
+
loadAndSetMessages(fsWithWatcher);
|
|
106
123
|
});
|
|
107
124
|
// -- installed items ----------------------------------------------------
|
|
108
125
|
const installedMessageLintRules = () => {
|
|
@@ -135,18 +152,22 @@ export const loadProject = async (args) => {
|
|
|
135
152
|
const lintReportsQuery = createMessageLintReportsQuery(messages, settings, installedMessageLintRules, resolvedModules);
|
|
136
153
|
const debouncedSave = skipFirst(debounce(500, async (newMessages) => {
|
|
137
154
|
try {
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
155
|
+
if (JSON.stringify(newMessages) !== JSON.stringify(messages())) {
|
|
156
|
+
await resolvedModules()?.resolvedPluginApi.saveMessages({
|
|
157
|
+
settings: settingsValue,
|
|
158
|
+
messages: newMessages,
|
|
159
|
+
});
|
|
160
|
+
}
|
|
142
161
|
}
|
|
143
162
|
catch (err) {
|
|
144
163
|
throw new PluginSaveMessagesError({
|
|
145
164
|
cause: err,
|
|
146
165
|
});
|
|
147
166
|
}
|
|
167
|
+
const abortController = new AbortController();
|
|
148
168
|
if (newMessages.length !== 0 &&
|
|
149
|
-
JSON.stringify(newMessages) !== JSON.stringify(messages())
|
|
169
|
+
JSON.stringify(newMessages) !== JSON.stringify(messages()) &&
|
|
170
|
+
nodeishFs.watch("/", { signal: abortController.signal }) === undefined) {
|
|
150
171
|
setMessages(newMessages);
|
|
151
172
|
}
|
|
152
173
|
}, { atBegin: false }));
|
|
@@ -225,7 +246,7 @@ const _writeSettingsToDisk = async (args) => {
|
|
|
225
246
|
if (serializeSettingsError) {
|
|
226
247
|
throw serializeSettingsError;
|
|
227
248
|
}
|
|
228
|
-
const { error: writeSettingsError } = await tryCatch(async () => args.nodeishFs.writeFile("
|
|
249
|
+
const { error: writeSettingsError } = await tryCatch(async () => args.nodeishFs.writeFile(args.projectPath + "/settings.json", serializedSettings));
|
|
229
250
|
if (writeSettingsError) {
|
|
230
251
|
throw writeSettingsError;
|
|
231
252
|
}
|