@inlang/sdk 0.18.0 → 0.20.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/README.md +1 -1
- package/dist/adapter/solidAdapter.test.js +16 -15
- package/dist/createMessageLintReportsQuery.d.ts +2 -3
- package/dist/createMessageLintReportsQuery.d.ts.map +1 -1
- package/dist/createMessageLintReportsQuery.js +42 -21
- package/dist/createNodeishFsWithAbsolutePaths.d.ts +2 -2
- package/dist/createNodeishFsWithAbsolutePaths.d.ts.map +1 -1
- package/dist/createNodeishFsWithAbsolutePaths.js +4 -4
- package/dist/createNodeishFsWithAbsolutePaths.test.js +4 -4
- package/dist/createNodeishFsWithWatcher.d.ts +1 -1
- package/dist/createNodeishFsWithWatcher.d.ts.map +1 -1
- package/dist/createNodeishFsWithWatcher.js +6 -4
- package/dist/generateProjectId.d.ts +3 -0
- package/dist/generateProjectId.d.ts.map +1 -0
- package/dist/generateProjectId.js +11 -0
- package/dist/generateProjectId.test.d.ts +2 -0
- package/dist/generateProjectId.test.d.ts.map +1 -0
- package/dist/generateProjectId.test.js +18 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/isAbsolutePath.test.js +1 -1
- package/dist/listProjects.d.ts +5 -0
- package/dist/listProjects.d.ts.map +1 -0
- package/dist/listProjects.js +31 -0
- package/dist/listProjects.test.d.ts +2 -0
- package/dist/listProjects.test.d.ts.map +1 -0
- package/dist/listProjects.test.js +56 -0
- package/dist/loadProject.d.ts +6 -4
- package/dist/loadProject.d.ts.map +1 -1
- package/dist/loadProject.js +58 -22
- package/dist/loadProject.test.js +157 -75
- 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/validateModuleSettings.test.js +1 -1
- package/package.json +57 -56
- package/src/adapter/solidAdapter.test.ts +16 -15
- package/src/createMessageLintReportsQuery.ts +57 -28
- package/src/createNodeishFsWithAbsolutePaths.test.ts +4 -4
- package/src/createNodeishFsWithAbsolutePaths.ts +5 -5
- package/src/createNodeishFsWithWatcher.ts +6 -4
- package/src/generateProjectId.test.ts +22 -0
- package/src/generateProjectId.ts +14 -0
- package/src/index.ts +1 -0
- package/src/isAbsolutePath.test.ts +1 -1
- package/src/listProjects.test.ts +69 -0
- package/src/listProjects.ts +39 -0
- package/src/loadProject.test.ts +182 -76
- package/src/loadProject.ts +77 -28
- package/src/migrations/migrateToDirectory.test.ts +54 -0
- package/src/migrations/migrateToDirectory.ts +59 -0
- package/src/resolve-modules/validateModuleSettings.test.ts +1 -1
package/README.md
CHANGED
|
@@ -13,4 +13,4 @@ Developer-first localization infrastructure that is built on git. Your git repos
|
|
|
13
13
|
|
|
14
14
|
# @inlang/sdk
|
|
15
15
|
|
|
16
|
-
The core module bundles "sdk" modules that depend on each other and is everything one needs to build [plugins](https://inlang.com/documentation/plugin) or entire [apps](https://inlang.com/documentation/
|
|
16
|
+
The core module bundles "sdk" modules that depend on each other and is everything one needs to build [plugins](https://inlang.com/documentation/plugin) or entire [apps](https://inlang.com/documentation/build-app) on inlang.
|
|
@@ -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 });
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import type { InlangProject, InstalledMessageLintRule } from "./api.js";
|
|
1
|
+
import type { InlangProject, InstalledMessageLintRule, MessageQueryApi } from "./api.js";
|
|
2
2
|
import type { ProjectSettings } from "@inlang/project-settings";
|
|
3
3
|
import type { resolveModules } from "./resolve-modules/index.js";
|
|
4
|
-
import type { Message } from "./versionedInterfaces.js";
|
|
5
4
|
/**
|
|
6
5
|
* Creates a reactive query API for messages.
|
|
7
6
|
*/
|
|
8
|
-
export declare function createMessageLintReportsQuery(
|
|
7
|
+
export declare function createMessageLintReportsQuery(messagesQuery: MessageQueryApi, settings: () => ProjectSettings, installedMessageLintRules: () => Array<InstalledMessageLintRule>, resolvedModules: () => Awaited<ReturnType<typeof resolveModules>> | undefined, hasWatcher: boolean): InlangProject["query"]["messageLintReports"];
|
|
9
8
|
//# sourceMappingURL=createMessageLintReportsQuery.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createMessageLintReportsQuery.d.ts","sourceRoot":"","sources":["../src/createMessageLintReportsQuery.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"createMessageLintReportsQuery.d.ts","sourceRoot":"","sources":["../src/createMessageLintReportsQuery.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACX,aAAa,EACb,wBAAwB,EAExB,eAAe,EACf,MAAM,UAAU,CAAA;AACjB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAA;AAC/D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAA;AAOhE;;GAEG;AACH,wBAAgB,6BAA6B,CAC5C,aAAa,EAAE,eAAe,EAC9B,QAAQ,EAAE,MAAM,eAAe,EAC/B,yBAAyB,EAAE,MAAM,KAAK,CAAC,wBAAwB,CAAC,EAChE,eAAe,EAAE,MAAM,OAAO,CAAC,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC,GAAG,SAAS,EAC7E,UAAU,EAAE,OAAO,GACjB,aAAa,CAAC,OAAO,CAAC,CAAC,oBAAoB,CAAC,CA2E9C"}
|
|
@@ -1,33 +1,54 @@
|
|
|
1
|
-
import { createEffect } from "./reactivity/solid.js";
|
|
2
1
|
import { createSubscribable } from "./loadProject.js";
|
|
3
2
|
import { lintSingleMessage } from "./lint/index.js";
|
|
4
3
|
import { ReactiveMap } from "./reactivity/map.js";
|
|
4
|
+
import { debounce } from "throttle-debounce";
|
|
5
|
+
import { createEffect } from "./reactivity/solid.js";
|
|
5
6
|
/**
|
|
6
7
|
* Creates a reactive query API for messages.
|
|
7
8
|
*/
|
|
8
|
-
export function createMessageLintReportsQuery(
|
|
9
|
+
export function createMessageLintReportsQuery(messagesQuery, settings, installedMessageLintRules, resolvedModules, hasWatcher) {
|
|
9
10
|
// @ts-expect-error
|
|
10
11
|
const index = new ReactiveMap();
|
|
12
|
+
const modules = resolvedModules();
|
|
13
|
+
const rulesArray = modules?.messageLintRules;
|
|
14
|
+
const messageLintRuleLevels = Object.fromEntries(installedMessageLintRules().map((rule) => [rule.id, rule.level]));
|
|
15
|
+
const settingsObject = () => {
|
|
16
|
+
return {
|
|
17
|
+
...settings(),
|
|
18
|
+
messageLintRuleLevels,
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
const messages = messagesQuery.getAll();
|
|
11
22
|
createEffect(() => {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
23
|
+
if (rulesArray) {
|
|
24
|
+
for (const messageId of messagesQuery.includedMessageIds()) {
|
|
25
|
+
createEffect(() => {
|
|
26
|
+
const message = messagesQuery.get({ where: { id: messageId } });
|
|
27
|
+
if (hasWatcher) {
|
|
28
|
+
lintSingleMessage({
|
|
29
|
+
rules: rulesArray,
|
|
30
|
+
settings: settingsObject(),
|
|
31
|
+
messages: messages,
|
|
32
|
+
message: message,
|
|
33
|
+
}).then((report) => {
|
|
34
|
+
if (report.errors.length === 0 && index.get(messageId) !== report.data) {
|
|
35
|
+
index.set(messageId, report.data);
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
debounce(500, (message) => {
|
|
41
|
+
lintSingleMessage({
|
|
42
|
+
rules: rulesArray,
|
|
43
|
+
settings: settingsObject(),
|
|
44
|
+
messages: messages,
|
|
45
|
+
message: message,
|
|
46
|
+
}).then((report) => {
|
|
47
|
+
if (report.errors.length === 0 && index.get(messageId) !== report.data) {
|
|
48
|
+
index.set(messageId, report.data);
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
}, { atBegin: false })(message);
|
|
31
52
|
}
|
|
32
53
|
});
|
|
33
54
|
}
|
|
@@ -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);
|
|
@@ -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`],
|
|
@@ -23,7 +23,7 @@ it("intercepts paths correctly for readFile", async () => {
|
|
|
23
23
|
watch: vi.fn(),
|
|
24
24
|
};
|
|
25
25
|
const interceptedFs = createNodeishFsWithAbsolutePaths({
|
|
26
|
-
|
|
26
|
+
projectPath,
|
|
27
27
|
nodeishFs: mockNodeishFs,
|
|
28
28
|
});
|
|
29
29
|
for (const [path, expectedPath] of filePaths) {
|
|
@@ -3,7 +3,7 @@ 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 createNodeishFsWithWatcher: (args: {
|
|
9
9
|
nodeishFs: NodeishFilesystemSubset;
|
|
@@ -1 +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,
|
|
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"}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Wraps the nodeish filesystem subset with a function that intercepts paths
|
|
3
3
|
* and prepends the base path.
|
|
4
4
|
*
|
|
5
|
-
* The paths are resolved from the `
|
|
5
|
+
* The paths are resolved from the `projectPath` argument.
|
|
6
6
|
*/
|
|
7
7
|
export const createNodeishFsWithWatcher = (args) => {
|
|
8
8
|
const pathList = [];
|
|
@@ -14,9 +14,11 @@ export const createNodeishFsWithWatcher = (args) => {
|
|
|
14
14
|
signal: abortController.signal,
|
|
15
15
|
persistent: false,
|
|
16
16
|
});
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
if (watcher) {
|
|
18
|
+
//eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
19
|
+
for await (const event of watcher) {
|
|
20
|
+
args.updateMessages();
|
|
21
|
+
}
|
|
20
22
|
}
|
|
21
23
|
}
|
|
22
24
|
catch (err) {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generateProjectId.d.ts","sourceRoot":"","sources":["../src/generateProjectId.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAGhD,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,+BAU5E"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { hash } from "@lix-js/client";
|
|
2
|
+
export async function generateProjectId(repo, projectPath) {
|
|
3
|
+
if (!repo || !projectPath) {
|
|
4
|
+
return undefined;
|
|
5
|
+
}
|
|
6
|
+
const repoMeta = await repo.getMeta();
|
|
7
|
+
if (repoMeta && !("error" in repoMeta)) {
|
|
8
|
+
return hash(`${repoMeta.id + projectPath}`);
|
|
9
|
+
}
|
|
10
|
+
return undefined;
|
|
11
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generateProjectId.test.d.ts","sourceRoot":"","sources":["../src/generateProjectId.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { generateProjectId } from "./generateProjectId.js";
|
|
2
|
+
import { describe, it, expect } from "vitest";
|
|
3
|
+
import { openRepository } from "@lix-js/client/src/openRepository.ts";
|
|
4
|
+
import { mockRepo, createNodeishMemoryFs } from "@lix-js/client";
|
|
5
|
+
describe("generateProjectId", async () => {
|
|
6
|
+
const repo = await mockRepo();
|
|
7
|
+
it("should generate a project id", async () => {
|
|
8
|
+
const projectId = await generateProjectId(repo, "mocked_project_path");
|
|
9
|
+
expect(projectId).toBe("0c83325bf9068eb01091c522d4b8e3765aff42e36fc781c041b44439bbe3e734");
|
|
10
|
+
});
|
|
11
|
+
it("should return undefined if repoMeta contains error", async () => {
|
|
12
|
+
const errorRepo = await openRepository("https://github.com/inlang/no-exist", {
|
|
13
|
+
nodeishFs: createNodeishMemoryFs(),
|
|
14
|
+
});
|
|
15
|
+
const projectId = await generateProjectId(errorRepo, "mocked_project_path");
|
|
16
|
+
expect(projectId).toBeUndefined();
|
|
17
|
+
});
|
|
18
|
+
});
|
package/dist/index.d.ts
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
export type { InlangProject, InstalledMessageLintRule, InstalledPlugin, MessageQueryApi, Subscribable, } from "./api.js";
|
|
7
7
|
export { type ImportFunction, createImport } from "./resolve-modules/index.js";
|
|
8
8
|
export { loadProject } from "./loadProject.js";
|
|
9
|
+
export { listProjects } from "./listProjects.js";
|
|
9
10
|
export { solidAdapter, type InlangProjectWithSolidAdapter } from "./adapter/solidAdapter.js";
|
|
10
11
|
export { createMessagesQuery } from "./createMessagesQuery.js";
|
|
11
12
|
export { ProjectSettingsFileJSONSyntaxError, ProjectSettingsFileNotFoundError, ProjectSettingsInvalidError, PluginLoadMessagesError, PluginSaveMessagesError, } from "./errors.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,YAAY,EACX,aAAa,EACb,wBAAwB,EACxB,eAAe,EACf,eAAe,EACf,YAAY,GACZ,MAAM,UAAU,CAAA;AACjB,OAAO,EAAE,KAAK,cAAc,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAA;AAC9E,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAC9C,OAAO,EAAE,YAAY,EAAE,KAAK,6BAA6B,EAAE,MAAM,2BAA2B,CAAA;AAC5F,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAA;AAC9D,OAAO,EACN,kCAAkC,EAClC,gCAAgC,EAChC,2BAA2B,EAC3B,uBAAuB,EACvB,uBAAuB,GACvB,MAAM,aAAa,CAAA;AAEpB,cAAc,uBAAuB,CAAA;AACrC,cAAc,0BAA0B,CAAA;AACxC,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,YAAY,EACX,aAAa,EACb,wBAAwB,EACxB,eAAe,EACf,eAAe,EACf,YAAY,GACZ,MAAM,UAAU,CAAA;AACjB,OAAO,EAAE,KAAK,cAAc,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAA;AAC9E,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAChD,OAAO,EAAE,YAAY,EAAE,KAAK,6BAA6B,EAAE,MAAM,2BAA2B,CAAA;AAC5F,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAA;AAC9D,OAAO,EACN,kCAAkC,EAClC,gCAAgC,EAChC,2BAA2B,EAC3B,uBAAuB,EACvB,uBAAuB,GACvB,MAAM,aAAa,CAAA;AAEpB,cAAc,uBAAuB,CAAA;AACrC,cAAc,0BAA0B,CAAA;AACxC,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
export { createImport } from "./resolve-modules/index.js";
|
|
7
7
|
export { loadProject } from "./loadProject.js";
|
|
8
|
+
export { listProjects } from "./listProjects.js";
|
|
8
9
|
export { solidAdapter } from "./adapter/solidAdapter.js";
|
|
9
10
|
export { createMessagesQuery } from "./createMessagesQuery.js";
|
|
10
11
|
export { ProjectSettingsFileJSONSyntaxError, ProjectSettingsFileNotFoundError, ProjectSettingsInvalidError, PluginLoadMessagesError, PluginSaveMessagesError, } from "./errors.js";
|
|
@@ -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", () => {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"listProjects.d.ts","sourceRoot":"","sources":["../src/listProjects.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AAEnD,eAAO,MAAM,YAAY,cACb,iBAAiB,QACtB,MAAM,KACV,QAAQ,MAAM;IAAE,WAAW,EAAE,MAAM,CAAA;CAAE,CAAC,CAiCxC,CAAA"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export const listProjects = async (nodeishFs, from) => {
|
|
2
|
+
// !TODO: Remove this limit once we introduce caching
|
|
3
|
+
const recursionLimit = 5;
|
|
4
|
+
const projects = [];
|
|
5
|
+
async function searchDir(path, depth) {
|
|
6
|
+
if (depth > recursionLimit) {
|
|
7
|
+
return;
|
|
8
|
+
}
|
|
9
|
+
const files = await nodeishFs.readdir(path);
|
|
10
|
+
for (const file of files) {
|
|
11
|
+
const filePath = `${path}/${file}`;
|
|
12
|
+
const stats = await nodeishFs.stat(filePath);
|
|
13
|
+
if (stats.isDirectory()) {
|
|
14
|
+
if (file === "node_modules")
|
|
15
|
+
continue;
|
|
16
|
+
if (file.endsWith(".inlang")) {
|
|
17
|
+
projects.push({ projectPath: filePath });
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
await searchDir(filePath, depth + 1);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
await searchDir(from, 0);
|
|
26
|
+
// remove double slashes
|
|
27
|
+
for (const project of projects) {
|
|
28
|
+
project.projectPath = project.projectPath.replace(/\/\//g, "/");
|
|
29
|
+
}
|
|
30
|
+
return projects;
|
|
31
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"listProjects.test.d.ts","sourceRoot":"","sources":["../src/listProjects.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { assert, describe, it } from "vitest";
|
|
2
|
+
import { listProjects } from "./listProjects.js";
|
|
3
|
+
import { createNodeishMemoryFs } from "@lix-js/fs";
|
|
4
|
+
const settings = {
|
|
5
|
+
sourceLanguageTag: "en",
|
|
6
|
+
languageTags: ["en"],
|
|
7
|
+
modules: ["plugin.js", "lintRule.js"],
|
|
8
|
+
messageLintRuleLevels: {
|
|
9
|
+
"messageLintRule.project.missingTranslation": "error",
|
|
10
|
+
},
|
|
11
|
+
"plugin.project.i18next": {
|
|
12
|
+
pathPattern: "./examples/example01/{languageTag}.json",
|
|
13
|
+
variableReferencePattern: ["{", "}"],
|
|
14
|
+
},
|
|
15
|
+
};
|
|
16
|
+
describe("listProjects", () => {
|
|
17
|
+
it("should find all projects a given path", async () => {
|
|
18
|
+
const fs = createNodeishMemoryFs();
|
|
19
|
+
await fs.mkdir("/user/dir1/project.inlang", { recursive: true });
|
|
20
|
+
await fs.writeFile("/user/dir1/project.inlang/settings.json", JSON.stringify(settings));
|
|
21
|
+
await fs.mkdir("/user/dir2/project.inlang", { recursive: true });
|
|
22
|
+
await fs.writeFile("/user/dir2/project.inlang/settings.json", JSON.stringify(settings));
|
|
23
|
+
await listProjects(fs, "/user").then((projects) => {
|
|
24
|
+
assert(projects.length === 2);
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
it("should return objects inside of an array with the projectPath", async () => {
|
|
28
|
+
const fs = createNodeishMemoryFs();
|
|
29
|
+
await fs.mkdir("/user/dir1/project.inlang", { recursive: true });
|
|
30
|
+
await fs.writeFile("/user/dir1/project.inlang/settings.json", JSON.stringify(settings));
|
|
31
|
+
await fs.mkdir("/user/dir2/project.inlang", { recursive: true });
|
|
32
|
+
await fs.writeFile("/user/dir2/project.inlang/settings.json", JSON.stringify(settings));
|
|
33
|
+
await listProjects(fs, "/user").then((projects) => {
|
|
34
|
+
assert.isTrue(typeof projects[0] === "object");
|
|
35
|
+
assert.isTrue(typeof projects[0]?.projectPath === "string");
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
it("should limit the recursion depth to 5", async () => {
|
|
39
|
+
const fs = createNodeishMemoryFs();
|
|
40
|
+
await fs.mkdir("/user/dir1/dir2/dir3/dir4/dir5/dir6/project.inlang", { recursive: true });
|
|
41
|
+
await fs.writeFile("/user/dir1/dir2/dir3/dir4/dir5/dir6/project.inlang/settings.json", JSON.stringify(settings));
|
|
42
|
+
await listProjects(fs, "/user").then((projects) => {
|
|
43
|
+
assert(projects.length === 0);
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
it("should also find files inside of a dir that ends with *.inlang", async () => {
|
|
47
|
+
const fs = createNodeishMemoryFs();
|
|
48
|
+
await fs.mkdir("/user/dir1/go.inlang", { recursive: true });
|
|
49
|
+
await fs.writeFile("/user/dir1/go.inlang/settings.json", JSON.stringify(settings));
|
|
50
|
+
await fs.mkdir("/user/dir2/flutter.inlang", { recursive: true });
|
|
51
|
+
await fs.writeFile("/user/dir2/flutter.inlang/settings.json", JSON.stringify(settings));
|
|
52
|
+
await listProjects(fs, "/user").then((projects) => {
|
|
53
|
+
assert(projects.length === 2);
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
});
|
package/dist/loadProject.d.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
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
|
+
import type { Repository } from "@lix-js/client";
|
|
4
5
|
/**
|
|
5
6
|
* Creates an inlang instance.
|
|
6
7
|
*
|
|
7
|
-
* @param
|
|
8
|
+
* @param projectPath - Absolute path to the inlang settings file.
|
|
8
9
|
* @param nodeishFs - Filesystem that implements the NodeishFilesystemSubset interface.
|
|
9
10
|
* @param _import - Use `_import` to pass a custom import function for testing,
|
|
10
11
|
* and supporting legacy resolvedModules such as CJS.
|
|
@@ -12,8 +13,9 @@ import { type NodeishFilesystemSubset } from "./versionedInterfaces.js";
|
|
|
12
13
|
*
|
|
13
14
|
*/
|
|
14
15
|
export declare const loadProject: (args: {
|
|
15
|
-
|
|
16
|
-
|
|
16
|
+
projectPath: string;
|
|
17
|
+
repo?: Repository | undefined;
|
|
18
|
+
nodeishFs: NodeishFilesystem;
|
|
17
19
|
_import?: ImportFunction | undefined;
|
|
18
20
|
_capture?: ((id: string, props: Record<string, unknown>) => void) | undefined;
|
|
19
21
|
}) => 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;AAIlE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAKhD;;;;;;;;;GASG;AACH,eAAO,MAAM,WAAW;iBACV,MAAM;;eAER,iBAAiB;;qBAEZ,MAAM,SAAS,OAAO,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI;MAC5D,QAAQ,aAAa,CAkQxB,CAAA;AAwHD,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,YAAY,CAAC,CAAC,CAAC,CAQtE"}
|