@inlang/sdk 0.32.0 → 0.34.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/createNewProject.d.ts +17 -0
- package/dist/createNewProject.d.ts.map +1 -0
- package/dist/createNewProject.js +22 -0
- package/dist/createNewProject.test.d.ts +2 -0
- package/dist/createNewProject.test.d.ts.map +1 -0
- package/dist/createNewProject.test.js +93 -0
- package/dist/createNodeishFsWithAbsolutePaths.js +1 -1
- package/dist/defaultProjectSettings.d.ts +14 -0
- package/dist/defaultProjectSettings.d.ts.map +1 -0
- package/dist/defaultProjectSettings.js +23 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/loadProject.d.ts.map +1 -1
- package/dist/loadProject.js +19 -23
- package/dist/loadProject.test.js +4 -4
- package/dist/migrations/maybeCreateFirstProjectId.test.js +3 -6
- package/dist/storage/helper.d.ts +24 -0
- package/dist/storage/helper.d.ts.map +1 -1
- package/dist/storage/helper.js +35 -7
- package/dist/storage/helpers.test.d.ts +2 -0
- package/dist/storage/helpers.test.d.ts.map +1 -0
- package/dist/storage/helpers.test.js +84 -0
- package/dist/validateProjectPath.d.ts +23 -0
- package/dist/validateProjectPath.d.ts.map +1 -0
- package/dist/validateProjectPath.js +52 -0
- package/dist/validateProjectPath.test.d.ts +2 -0
- package/dist/validateProjectPath.test.d.ts.map +1 -0
- package/dist/validateProjectPath.test.js +56 -0
- package/package.json +7 -7
- package/src/createNewProject.test.ts +108 -0
- package/src/createNewProject.ts +31 -0
- package/src/createNodeishFsWithAbsolutePaths.ts +1 -1
- package/src/defaultProjectSettings.ts +27 -0
- package/src/index.ts +3 -0
- package/src/loadProject.test.ts +5 -4
- package/src/loadProject.ts +22 -28
- package/src/migrations/maybeCreateFirstProjectId.test.ts +3 -6
- package/src/storage/helper.ts +36 -10
- package/src/storage/helpers.test.ts +95 -0
- package/src/validateProjectPath.test.ts +68 -0
- package/src/validateProjectPath.ts +58 -0
- package/dist/isAbsolutePath.d.ts +0 -2
- package/dist/isAbsolutePath.d.ts.map +0 -1
- package/dist/isAbsolutePath.js +0 -4
- package/dist/isAbsolutePath.test.d.ts +0 -2
- package/dist/isAbsolutePath.test.d.ts.map +0 -1
- package/dist/isAbsolutePath.test.js +0 -20
- package/src/isAbsolutePath.test.ts +0 -23
- package/src/isAbsolutePath.ts +0 -5
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest"
|
|
2
|
+
// import { parseLixUri, parseOrigin } from "./helpers.js"
|
|
3
|
+
import { normalizeMessage, stringifyMessage } from "./helper.js"
|
|
4
|
+
import type { Message } from "@inlang/message"
|
|
5
|
+
|
|
6
|
+
const unsortedMessageRaw: Message = {
|
|
7
|
+
alias: {},
|
|
8
|
+
selectors: [],
|
|
9
|
+
id: "footer_categories_apps",
|
|
10
|
+
variants: [
|
|
11
|
+
{ languageTag: "a", match: ["*", "1"], pattern: [{ type: "Text", value: "2" }] },
|
|
12
|
+
{ languageTag: "a", match: ["*", "*"], pattern: [{ type: "Text", value: "1" }] },
|
|
13
|
+
{
|
|
14
|
+
languageTag: "a",
|
|
15
|
+
match: ["1", "*"],
|
|
16
|
+
pattern: [
|
|
17
|
+
{ type: "Text", value: "2" },
|
|
18
|
+
{ type: "Text", value: "2" },
|
|
19
|
+
],
|
|
20
|
+
},
|
|
21
|
+
{ languageTag: "b", match: [], pattern: [{ type: "Text", value: "4" }] },
|
|
22
|
+
{ languageTag: "a", match: ["1", "1"], pattern: [{ type: "Text", value: "2" }] },
|
|
23
|
+
{ languageTag: "c", match: [], pattern: [{ value: "5", type: "Text" }] },
|
|
24
|
+
{ match: [], languageTag: "d", pattern: [{ type: "Text", value: "6" }] },
|
|
25
|
+
{ languageTag: "e", match: [], pattern: [{ type: "Text", value: "7" }] },
|
|
26
|
+
{ languageTag: "f", match: [], pattern: [{ type: "Text", value: "8" }] },
|
|
27
|
+
{ languageTag: "g", match: [], pattern: [{ type: "Text", value: "9" }] },
|
|
28
|
+
],
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const sortedMessageRaw: Message = {
|
|
32
|
+
alias: {},
|
|
33
|
+
id: "footer_categories_apps",
|
|
34
|
+
selectors: [],
|
|
35
|
+
variants: [
|
|
36
|
+
{ languageTag: "a", match: ["*", "*"], pattern: [{ type: "Text", value: "1" }] },
|
|
37
|
+
{ languageTag: "a", match: ["*", "1"], pattern: [{ type: "Text", value: "2" }] },
|
|
38
|
+
{
|
|
39
|
+
languageTag: "a",
|
|
40
|
+
match: ["1", "*"],
|
|
41
|
+
pattern: [
|
|
42
|
+
{ type: "Text", value: "2" },
|
|
43
|
+
{ type: "Text", value: "2" },
|
|
44
|
+
],
|
|
45
|
+
},
|
|
46
|
+
{ languageTag: "a", match: ["1", "1"], pattern: [{ type: "Text", value: "2" }] },
|
|
47
|
+
{ languageTag: "b", match: [], pattern: [{ type: "Text", value: "4" }] },
|
|
48
|
+
{ languageTag: "c", match: [], pattern: [{ type: "Text", value: "5" }] },
|
|
49
|
+
{ languageTag: "d", match: [], pattern: [{ type: "Text", value: "6" }] },
|
|
50
|
+
{ languageTag: "e", match: [], pattern: [{ type: "Text", value: "7" }] },
|
|
51
|
+
{ languageTag: "f", match: [], pattern: [{ type: "Text", value: "8" }] },
|
|
52
|
+
{ languageTag: "g", match: [], pattern: [{ type: "Text", value: "9" }] },
|
|
53
|
+
],
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// stringify with no indentation
|
|
57
|
+
function str(obj: any) {
|
|
58
|
+
return JSON.stringify(obj)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// stringify with 2 space indentation
|
|
62
|
+
function str2(obj: any) {
|
|
63
|
+
return JSON.stringify(obj, undefined, 2)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// stringify with 4 space indentation
|
|
67
|
+
function str4(obj: any) {
|
|
68
|
+
return JSON.stringify(obj, undefined, 4)
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
describe("normalizeMessage", () => {
|
|
72
|
+
it("should return the message with sorted keys and variants", () => {
|
|
73
|
+
// test cases are not the same (deep equal) before normalization
|
|
74
|
+
// array order of variants is different
|
|
75
|
+
expect(unsortedMessageRaw).not.toEqual(sortedMessageRaw)
|
|
76
|
+
|
|
77
|
+
// test cases are the same after normalization
|
|
78
|
+
expect(normalizeMessage(unsortedMessageRaw)).toEqual(sortedMessageRaw)
|
|
79
|
+
|
|
80
|
+
// stringify results are not the same before normalization
|
|
81
|
+
expect(str(unsortedMessageRaw)).not.toBe(str(sortedMessageRaw))
|
|
82
|
+
|
|
83
|
+
// stringify results are the same after normalization
|
|
84
|
+
expect(str(normalizeMessage(unsortedMessageRaw))).toBe(str(sortedMessageRaw))
|
|
85
|
+
expect(str2(normalizeMessage(unsortedMessageRaw))).toBe(str2(sortedMessageRaw))
|
|
86
|
+
expect(str4(normalizeMessage(unsortedMessageRaw))).toBe(str4(sortedMessageRaw))
|
|
87
|
+
})
|
|
88
|
+
})
|
|
89
|
+
|
|
90
|
+
describe("stringifyMessage", () => {
|
|
91
|
+
it("should normalize and JSON stringify a message with 4 space indentation", () => {
|
|
92
|
+
expect(stringifyMessage(unsortedMessageRaw)).toBe(str4(sortedMessageRaw))
|
|
93
|
+
expect(stringifyMessage(sortedMessageRaw)).toBe(str4(sortedMessageRaw))
|
|
94
|
+
})
|
|
95
|
+
})
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { assert, describe, expect, it } from "vitest"
|
|
2
|
+
import {
|
|
3
|
+
assertValidProjectPath,
|
|
4
|
+
isAbsolutePath,
|
|
5
|
+
isInlangProjectPath,
|
|
6
|
+
pathExists,
|
|
7
|
+
} from "./validateProjectPath.js"
|
|
8
|
+
import { mockRepo } from "@lix-js/client"
|
|
9
|
+
|
|
10
|
+
describe("isAbsolutePath", () => {
|
|
11
|
+
it("should correctly identify Unix absolute paths", () => {
|
|
12
|
+
assert.isTrue(isAbsolutePath("/home/user/documents/file.txt"))
|
|
13
|
+
assert.isTrue(isAbsolutePath("/usr/local/bin/script.sh"))
|
|
14
|
+
assert.isFalse(isAbsolutePath("relative/path/to/file.txt"))
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
it("should correctly identify Windows absolute paths", () => {
|
|
18
|
+
assert.isTrue(isAbsolutePath("C:\\Users\\User\\Documents\\File.txt"))
|
|
19
|
+
assert.isTrue(isAbsolutePath("C:/Users/user/project.inlang/settings.json"))
|
|
20
|
+
assert.isFalse(isAbsolutePath("Projects\\Project1\\source\\file.txt"))
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
it("should handle edge cases", () => {
|
|
24
|
+
assert.isFalse(isAbsolutePath("")) // Empty path should return false
|
|
25
|
+
assert.isFalse(isAbsolutePath("relative/path/../file.txt")) // Relative path with ".." should return false
|
|
26
|
+
assert.isFalse(isAbsolutePath("../relative/path/to/file.txt"))
|
|
27
|
+
assert.isFalse(isAbsolutePath("./relative/path/to/file.txt"))
|
|
28
|
+
})
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
describe("isInlangProjectPath", () => {
|
|
32
|
+
it("should correctly identify valid inlang project paths", () => {
|
|
33
|
+
assert.isTrue(isInlangProjectPath("/path/to/orange-mouse.inlang"))
|
|
34
|
+
assert.isFalse(isInlangProjectPath("relative/path/to/file.txt"))
|
|
35
|
+
assert.isFalse(isInlangProjectPath("/path/to/.inlang"))
|
|
36
|
+
assert.isFalse(isInlangProjectPath("/path/to/white-elephant.inlang/"))
|
|
37
|
+
assert.isFalse(isInlangProjectPath("/path/to/blue-elephant.inlang/settings.json"))
|
|
38
|
+
})
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
describe("assertValidProjectPath", () => {
|
|
42
|
+
it("should not throw for valid project paths", () => {
|
|
43
|
+
assert.doesNotThrow(() => assertValidProjectPath("/path/to/brown-mouse.inlang"))
|
|
44
|
+
assert.doesNotThrow(() => assertValidProjectPath("/path/to/green-elephant.inlang"))
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
it("should throw for invalid project paths", () => {
|
|
48
|
+
assert.throws(() => assertValidProjectPath("relative/path/to/flying-lizard.inlang"))
|
|
49
|
+
assert.throws(() => assertValidProjectPath("/path/to/loud-mouse.inlang/"))
|
|
50
|
+
assert.throws(() => assertValidProjectPath("/path/to/green-elephant.inlang/settings.json"))
|
|
51
|
+
})
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
// moar tests in paraglide-js/src/services/file-handling/exists.test.ts
|
|
55
|
+
describe("pathExists", () => {
|
|
56
|
+
it("should work for files", async () => {
|
|
57
|
+
const repo = await mockRepo()
|
|
58
|
+
await repo.nodeishFs.writeFile("/test.txt", "hello")
|
|
59
|
+
expect(await pathExists("/test.txt", repo.nodeishFs)).toBe(true)
|
|
60
|
+
expect(await pathExists("/does-not-exist.txt", repo.nodeishFs)).toBe(false)
|
|
61
|
+
})
|
|
62
|
+
it("should work for directories", async () => {
|
|
63
|
+
const repo = await mockRepo()
|
|
64
|
+
await repo.nodeishFs.mkdir("/test/project.inlang", { recursive: true })
|
|
65
|
+
expect(await pathExists("/test/project.inlang", repo.nodeishFs)).toBe(true)
|
|
66
|
+
expect(await pathExists("/test/white-gorilla.inlang", repo.nodeishFs)).toBe(false)
|
|
67
|
+
})
|
|
68
|
+
})
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type { NodeishFilesystem } from "@lix-js/fs"
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* validate that a project path is absolute and ends with {name}.inlang.
|
|
5
|
+
*
|
|
6
|
+
* @throws if the path is not valid.
|
|
7
|
+
*/
|
|
8
|
+
export function assertValidProjectPath(projectPath: string) {
|
|
9
|
+
if (!isAbsolutePath(projectPath)) {
|
|
10
|
+
throw new Error(`Expected an absolute path but received "${projectPath}".`)
|
|
11
|
+
}
|
|
12
|
+
if (!isInlangProjectPath(projectPath)) {
|
|
13
|
+
throw new Error(
|
|
14
|
+
`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`
|
|
15
|
+
)
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* tests whether a path ends with {name}.inlang
|
|
21
|
+
* (does not remove trailing slash)
|
|
22
|
+
*/
|
|
23
|
+
export function isInlangProjectPath(path: string) {
|
|
24
|
+
return /[^\\/]+\.inlang$/.test(path)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* tests whether a path starts with a forward slash (/) or a windows-style
|
|
29
|
+
* drive letter (C: or D:, etc.) followed by a slash
|
|
30
|
+
*/
|
|
31
|
+
export function isAbsolutePath(path: string) {
|
|
32
|
+
return /^\/|^[A-Za-z]:[\\/]/.test(path)
|
|
33
|
+
|
|
34
|
+
// OG from sdk/src/isAbsolutePath.ts - TODO: find out where this regex came from
|
|
35
|
+
// const matchPosixAndWindowsAbsolutePaths =
|
|
36
|
+
// /^(?:[A-Za-z]:\\(?:[^\\]+\\)*[^\\]+|[A-Za-z]:\/(?:[^/]+\/)*[^/]+|\/(?:[^/]+\/)*[^/]+)$/
|
|
37
|
+
// return matchPosixAndWindowsAbsolutePaths.test(path)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Returns true if the path exists (file or directory), false otherwise.
|
|
42
|
+
*
|
|
43
|
+
*/
|
|
44
|
+
export async function pathExists(filePath: string, nodeishFs: NodeishFilesystem) {
|
|
45
|
+
// from paraglide-js/src/services/file-handling/exists.ts
|
|
46
|
+
// TODO: add fs.exists to @lix-js/fs
|
|
47
|
+
try {
|
|
48
|
+
await nodeishFs.stat(filePath)
|
|
49
|
+
return true
|
|
50
|
+
} catch (error) {
|
|
51
|
+
//@ts-ignore
|
|
52
|
+
if (error.code === "ENOENT") {
|
|
53
|
+
return false
|
|
54
|
+
} else {
|
|
55
|
+
throw new Error(`Failed to check if path exists: ${error}`, { cause: error })
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
package/dist/isAbsolutePath.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"isAbsolutePath.d.ts","sourceRoot":"","sources":["../src/isAbsolutePath.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,cAAc,SAAU,MAAM,YAI1C,CAAA"}
|
package/dist/isAbsolutePath.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"isAbsolutePath.test.d.ts","sourceRoot":"","sources":["../src/isAbsolutePath.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { assert, describe, it } from "vitest";
|
|
2
|
-
import { isAbsolutePath } from "./isAbsolutePath.js";
|
|
3
|
-
describe("isAbsolutePath", () => {
|
|
4
|
-
it("should correctly identify Unix absolute paths", () => {
|
|
5
|
-
assert.isTrue(isAbsolutePath("/home/user/documents/file.txt"));
|
|
6
|
-
assert.isTrue(isAbsolutePath("/usr/local/bin/script.sh"));
|
|
7
|
-
assert.isFalse(isAbsolutePath("relative/path/to/file.txt"));
|
|
8
|
-
});
|
|
9
|
-
it("should correctly identify Windows absolute paths", () => {
|
|
10
|
-
assert.isTrue(isAbsolutePath("C:\\Users\\User\\Documents\\File.txt"));
|
|
11
|
-
assert.isTrue(isAbsolutePath("C:/Users/user/project.inlang/settings.json"));
|
|
12
|
-
assert.isFalse(isAbsolutePath("Projects\\Project1\\source\\file.txt"));
|
|
13
|
-
});
|
|
14
|
-
it("should handle edge cases", () => {
|
|
15
|
-
assert.isFalse(isAbsolutePath("")); // Empty path should return false
|
|
16
|
-
assert.isFalse(isAbsolutePath("relative/path/../file.txt")); // Relative path with ".." should return false
|
|
17
|
-
assert.isFalse(isAbsolutePath("../relative/path/to/file.txt"));
|
|
18
|
-
assert.isFalse(isAbsolutePath("./relative/path/to/file.txt"));
|
|
19
|
-
});
|
|
20
|
-
});
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { assert, describe, it } from "vitest"
|
|
2
|
-
import { isAbsolutePath } from "./isAbsolutePath.js"
|
|
3
|
-
|
|
4
|
-
describe("isAbsolutePath", () => {
|
|
5
|
-
it("should correctly identify Unix absolute paths", () => {
|
|
6
|
-
assert.isTrue(isAbsolutePath("/home/user/documents/file.txt"))
|
|
7
|
-
assert.isTrue(isAbsolutePath("/usr/local/bin/script.sh"))
|
|
8
|
-
assert.isFalse(isAbsolutePath("relative/path/to/file.txt"))
|
|
9
|
-
})
|
|
10
|
-
|
|
11
|
-
it("should correctly identify Windows absolute paths", () => {
|
|
12
|
-
assert.isTrue(isAbsolutePath("C:\\Users\\User\\Documents\\File.txt"))
|
|
13
|
-
assert.isTrue(isAbsolutePath("C:/Users/user/project.inlang/settings.json"))
|
|
14
|
-
assert.isFalse(isAbsolutePath("Projects\\Project1\\source\\file.txt"))
|
|
15
|
-
})
|
|
16
|
-
|
|
17
|
-
it("should handle edge cases", () => {
|
|
18
|
-
assert.isFalse(isAbsolutePath("")) // Empty path should return false
|
|
19
|
-
assert.isFalse(isAbsolutePath("relative/path/../file.txt")) // Relative path with ".." should return false
|
|
20
|
-
assert.isFalse(isAbsolutePath("../relative/path/to/file.txt"))
|
|
21
|
-
assert.isFalse(isAbsolutePath("./relative/path/to/file.txt"))
|
|
22
|
-
})
|
|
23
|
-
})
|
package/src/isAbsolutePath.ts
DELETED