@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/dist/loadProject.js
CHANGED
|
@@ -12,11 +12,13 @@ import { createNodeishFsWithAbsolutePaths } from "./createNodeishFsWithAbsoluteP
|
|
|
12
12
|
import { normalizePath } from "@lix-js/fs";
|
|
13
13
|
import { isAbsolutePath } from "./isAbsolutePath.js";
|
|
14
14
|
import { createNodeishFsWithWatcher } from "./createNodeishFsWithWatcher.js";
|
|
15
|
+
import { maybeMigrateToDirectory } from "./migrations/migrateToDirectory.js";
|
|
16
|
+
import { generateProjectId } from "./generateProjectId.js";
|
|
15
17
|
const settingsCompiler = TypeCompiler.Compile(ProjectSettings);
|
|
16
18
|
/**
|
|
17
19
|
* Creates an inlang instance.
|
|
18
20
|
*
|
|
19
|
-
* @param
|
|
21
|
+
* @param projectPath - Absolute path to the inlang settings file.
|
|
20
22
|
* @param nodeishFs - Filesystem that implements the NodeishFilesystemSubset interface.
|
|
21
23
|
* @param _import - Use `_import` to pass a custom import function for testing,
|
|
22
24
|
* and supporting legacy resolvedModules such as CJS.
|
|
@@ -24,37 +26,69 @@ const settingsCompiler = TypeCompiler.Compile(ProjectSettings);
|
|
|
24
26
|
*
|
|
25
27
|
*/
|
|
26
28
|
export const loadProject = async (args) => {
|
|
29
|
+
const projectPath = normalizePath(args.projectPath);
|
|
30
|
+
// -- migrate if outdated ------------------------------------------------
|
|
31
|
+
await maybeMigrateToDirectory({ nodeishFs: args.nodeishFs, projectPath });
|
|
27
32
|
// -- validation --------------------------------------------------------
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
if (!isAbsolutePath(args.
|
|
32
|
-
throw new LoadProjectInvalidArgument(`Expected an absolute path but received "${args.
|
|
33
|
+
// the only place where throwing is acceptable because the project
|
|
34
|
+
// won't even be loaded. do not throw anywhere else. otherwise, apps
|
|
35
|
+
// can't handle errors gracefully.
|
|
36
|
+
if (!isAbsolutePath(args.projectPath)) {
|
|
37
|
+
throw new LoadProjectInvalidArgument(`Expected an absolute path but received "${args.projectPath}".`, { argument: "projectPath" });
|
|
38
|
+
}
|
|
39
|
+
else if (/[^\\/]+\.inlang$/.test(projectPath) === false) {
|
|
40
|
+
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" });
|
|
33
41
|
}
|
|
34
|
-
const settingsFilePath = normalizePath(args.settingsFilePath);
|
|
35
42
|
// -- load project ------------------------------------------------------
|
|
43
|
+
let idError;
|
|
36
44
|
return await createRoot(async () => {
|
|
37
45
|
const [initialized, markInitAsComplete, markInitAsFailed] = createAwaitable();
|
|
38
46
|
const nodeishFs = createNodeishFsWithAbsolutePaths({
|
|
39
|
-
|
|
47
|
+
projectPath,
|
|
40
48
|
nodeishFs: args.nodeishFs,
|
|
41
49
|
});
|
|
50
|
+
let projectId;
|
|
51
|
+
try {
|
|
52
|
+
projectId = await nodeishFs.readFile(projectPath + "/project_id", {
|
|
53
|
+
encoding: "utf-8",
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
catch (error) {
|
|
57
|
+
// @ts-ignore
|
|
58
|
+
if (error.code === "ENOENT") {
|
|
59
|
+
if (args.repo) {
|
|
60
|
+
projectId = await generateProjectId(args.repo, projectPath);
|
|
61
|
+
if (projectId) {
|
|
62
|
+
await nodeishFs.writeFile(projectPath + "/project_id", projectId);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
idError = error;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
42
70
|
// -- settings ------------------------------------------------------------
|
|
43
71
|
const [settings, _setSettings] = createSignal();
|
|
44
72
|
createEffect(() => {
|
|
45
|
-
|
|
73
|
+
// TODO:
|
|
74
|
+
// if (projectId) {
|
|
75
|
+
// telemetryBrowser.group("project", projectId, {
|
|
76
|
+
// name: projectId,
|
|
77
|
+
// })
|
|
78
|
+
// }
|
|
79
|
+
loadSettings({ settingsFilePath: projectPath + "/settings.json", nodeishFs })
|
|
46
80
|
.then((settings) => {
|
|
47
81
|
setSettings(settings);
|
|
48
82
|
// rename settings to get a convenient access to the data in Posthog
|
|
49
83
|
const project_settings = settings;
|
|
50
|
-
args._capture?.("SDK used settings", { project_settings });
|
|
84
|
+
args._capture?.("SDK used settings", { project_settings, group: projectId });
|
|
51
85
|
})
|
|
52
86
|
.catch((err) => {
|
|
53
87
|
markInitAsFailed(err);
|
|
54
88
|
});
|
|
55
89
|
});
|
|
56
90
|
// TODO: create FS watcher and update settings on change
|
|
57
|
-
const writeSettingsToDisk = skipFirst((settings) => _writeSettingsToDisk({ nodeishFs, settings }));
|
|
91
|
+
const writeSettingsToDisk = skipFirst((settings) => _writeSettingsToDisk({ nodeishFs, settings, projectPath }));
|
|
58
92
|
const setSettings = (settings) => {
|
|
59
93
|
try {
|
|
60
94
|
const validatedSettings = parseSettings(settings);
|
|
@@ -84,11 +118,10 @@ export const loadProject = async (args) => {
|
|
|
84
118
|
// -- messages ----------------------------------------------------------
|
|
85
119
|
let settingsValue;
|
|
86
120
|
createEffect(() => (settingsValue = settings())); // workaround to not run effects twice (e.g. settings change + modules change) (I'm sure there exists a solid way of doing this, but I haven't found it yet)
|
|
121
|
+
// please don't use this as source of truth, use the query instead
|
|
122
|
+
// needed for granular linting
|
|
87
123
|
const [messages, setMessages] = createSignal();
|
|
88
124
|
createEffect(() => {
|
|
89
|
-
const conf = settings();
|
|
90
|
-
if (!conf)
|
|
91
|
-
return;
|
|
92
125
|
const _resolvedModules = resolvedModules();
|
|
93
126
|
if (!_resolvedModules)
|
|
94
127
|
return;
|
|
@@ -142,8 +175,10 @@ export const loadProject = async (args) => {
|
|
|
142
175
|
};
|
|
143
176
|
// -- app ---------------------------------------------------------------
|
|
144
177
|
const initializeError = await initialized.catch((error) => error);
|
|
178
|
+
const abortController = new AbortController();
|
|
179
|
+
const hasWatcher = nodeishFs.watch("/", { signal: abortController.signal }) !== undefined;
|
|
145
180
|
const messagesQuery = createMessagesQuery(() => messages() || []);
|
|
146
|
-
const lintReportsQuery = createMessageLintReportsQuery(
|
|
181
|
+
const lintReportsQuery = createMessageLintReportsQuery(messagesQuery, settings, installedMessageLintRules, resolvedModules, hasWatcher);
|
|
147
182
|
const debouncedSave = skipFirst(debounce(500, async (newMessages) => {
|
|
148
183
|
try {
|
|
149
184
|
if (JSON.stringify(newMessages) !== JSON.stringify(messages())) {
|
|
@@ -158,12 +193,12 @@ export const loadProject = async (args) => {
|
|
|
158
193
|
cause: err,
|
|
159
194
|
});
|
|
160
195
|
}
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
196
|
+
const abortController = new AbortController();
|
|
197
|
+
if (newMessages.length !== 0 &&
|
|
198
|
+
JSON.stringify(newMessages) !== JSON.stringify(messages()) &&
|
|
199
|
+
nodeishFs.watch("/", { signal: abortController.signal }) !== undefined) {
|
|
200
|
+
setMessages(newMessages);
|
|
201
|
+
}
|
|
167
202
|
}, { atBegin: false }));
|
|
168
203
|
createEffect(() => {
|
|
169
204
|
debouncedSave(messagesQuery.getAll());
|
|
@@ -175,6 +210,7 @@ export const loadProject = async (args) => {
|
|
|
175
210
|
},
|
|
176
211
|
errors: createSubscribable(() => [
|
|
177
212
|
...(initializeError ? [initializeError] : []),
|
|
213
|
+
...(idError ? [idError] : []),
|
|
178
214
|
...(resolvedModules() ? resolvedModules().errors : []),
|
|
179
215
|
// have a query error exposed
|
|
180
216
|
//...(lintErrors() ?? []),
|
|
@@ -240,7 +276,7 @@ const _writeSettingsToDisk = async (args) => {
|
|
|
240
276
|
if (serializeSettingsError) {
|
|
241
277
|
throw serializeSettingsError;
|
|
242
278
|
}
|
|
243
|
-
const { error: writeSettingsError } = await tryCatch(async () => args.nodeishFs.writeFile("
|
|
279
|
+
const { error: writeSettingsError } = await tryCatch(async () => args.nodeishFs.writeFile(args.projectPath + "/settings.json", serializedSettings));
|
|
244
280
|
if (writeSettingsError) {
|
|
245
281
|
throw writeSettingsError;
|
|
246
282
|
}
|
package/dist/loadProject.test.js
CHANGED
|
@@ -5,6 +5,7 @@ import { LoadProjectInvalidArgument, ProjectSettingsFileJSONSyntaxError, Project
|
|
|
5
5
|
import { createNodeishMemoryFs, normalizePath } from "@lix-js/fs";
|
|
6
6
|
import { createMessage } from "./test-utilities/createMessage.js";
|
|
7
7
|
import { tryCatch } from "@inlang/result";
|
|
8
|
+
import { mockRepo } from "@lix-js/client";
|
|
8
9
|
// ------------------------------------------------------------------------------------------------
|
|
9
10
|
const getValue = (subscribable) => {
|
|
10
11
|
let value;
|
|
@@ -80,23 +81,102 @@ const _import = async (name) => ({
|
|
|
80
81
|
default: name === "plugin.js" ? mockPlugin : mockMessageLintRule,
|
|
81
82
|
});
|
|
82
83
|
// ------------------------------------------------------------------------------------------------
|
|
84
|
+
/**
|
|
85
|
+
* Dear Developers,
|
|
86
|
+
*
|
|
87
|
+
* Inlang projects (folders) are not like .vscode, .git, or .github folders. Treat em
|
|
88
|
+
* like files: they can be renamed and moved around.
|
|
89
|
+
*/
|
|
90
|
+
it("should throw if a project (path) does not have a name", async () => {
|
|
91
|
+
const fs = createNodeishMemoryFs();
|
|
92
|
+
const project = await tryCatch(() => loadProject({
|
|
93
|
+
projectPath: "/source-code/.inlang",
|
|
94
|
+
nodeishFs: fs,
|
|
95
|
+
_import,
|
|
96
|
+
}));
|
|
97
|
+
expect(project.error).toBeInstanceOf(LoadProjectInvalidArgument);
|
|
98
|
+
});
|
|
99
|
+
it("should throw if a project path does not end with .inlang", async () => {
|
|
100
|
+
const fs = createNodeishMemoryFs();
|
|
101
|
+
const invalidPaths = [
|
|
102
|
+
"/source-code/frontend.inlang/settings",
|
|
103
|
+
"/source-code/frontend.inlang/settings.json",
|
|
104
|
+
"/source-code/frontend.inlang.md",
|
|
105
|
+
];
|
|
106
|
+
for (const invalidPath of invalidPaths) {
|
|
107
|
+
const project = await tryCatch(() => loadProject({
|
|
108
|
+
projectPath: invalidPath,
|
|
109
|
+
nodeishFs: fs,
|
|
110
|
+
_import,
|
|
111
|
+
}));
|
|
112
|
+
expect(project.error).toBeInstanceOf(LoadProjectInvalidArgument);
|
|
113
|
+
}
|
|
114
|
+
});
|
|
83
115
|
describe("initialization", () => {
|
|
84
|
-
it("should throw if
|
|
116
|
+
it("should throw if projectPath is not an absolute path", async () => {
|
|
85
117
|
const fs = createNodeishMemoryFs();
|
|
86
118
|
const result = await tryCatch(() => loadProject({
|
|
87
|
-
|
|
119
|
+
projectPath: "relative/path",
|
|
88
120
|
nodeishFs: fs,
|
|
89
121
|
_import,
|
|
90
122
|
}));
|
|
91
123
|
expect(result.error).toBeInstanceOf(LoadProjectInvalidArgument);
|
|
92
124
|
expect(result.data).toBeUndefined();
|
|
93
125
|
});
|
|
126
|
+
it("should generate projectId on missing projectid", async () => {
|
|
127
|
+
const repo = await mockRepo();
|
|
128
|
+
const existing = await repo.nodeishFs
|
|
129
|
+
.readFile("/project.inlang/project_id", {
|
|
130
|
+
encoding: "utf-8",
|
|
131
|
+
})
|
|
132
|
+
.catch((error) => {
|
|
133
|
+
return { error };
|
|
134
|
+
});
|
|
135
|
+
// @ts-ignore
|
|
136
|
+
expect(existing.error.code).toBe("ENOENT");
|
|
137
|
+
const result = await tryCatch(() => loadProject({
|
|
138
|
+
projectPath: "/project.inlang",
|
|
139
|
+
nodeishFs: repo.nodeishFs,
|
|
140
|
+
repo,
|
|
141
|
+
_import,
|
|
142
|
+
}));
|
|
143
|
+
const newId = await repo.nodeishFs
|
|
144
|
+
.readFile("/project.inlang/project_id", {
|
|
145
|
+
encoding: "utf-8",
|
|
146
|
+
})
|
|
147
|
+
.catch((error) => {
|
|
148
|
+
return { error };
|
|
149
|
+
});
|
|
150
|
+
expect(newId).toBe("7cd6c2b7cf12febf99496408917123fdfe158b6bc442914f5fb42aa74346bd50");
|
|
151
|
+
expect(result.error).toBeUndefined();
|
|
152
|
+
expect(result.data).toBeDefined();
|
|
153
|
+
});
|
|
154
|
+
it("should reuse projectId on existing projectid", async () => {
|
|
155
|
+
const repo = await mockRepo();
|
|
156
|
+
repo.nodeishFs.writeFile("/project.inlang/project_id", "testId");
|
|
157
|
+
const result = await tryCatch(() => loadProject({
|
|
158
|
+
projectPath: "/project.inlang",
|
|
159
|
+
nodeishFs: repo.nodeishFs,
|
|
160
|
+
repo,
|
|
161
|
+
_import,
|
|
162
|
+
}));
|
|
163
|
+
const newId = await repo.nodeishFs
|
|
164
|
+
.readFile("/project.inlang/project_id", {
|
|
165
|
+
encoding: "utf-8",
|
|
166
|
+
})
|
|
167
|
+
.catch((error) => {
|
|
168
|
+
return { error };
|
|
169
|
+
});
|
|
170
|
+
expect(newId).toBe("testId");
|
|
171
|
+
expect(result.error).toBeUndefined();
|
|
172
|
+
expect(result.data).toBeDefined();
|
|
173
|
+
});
|
|
94
174
|
it("should resolve from a windows path", async () => {
|
|
95
175
|
const fs = createNodeishMemoryFs();
|
|
96
|
-
fs.mkdir("C:\\Users\\user\\project", { recursive: true });
|
|
97
|
-
fs.writeFile("C:\\Users\\user\\project
|
|
176
|
+
fs.mkdir("C:\\Users\\user\\project.inlang", { recursive: true });
|
|
177
|
+
fs.writeFile("C:\\Users\\user\\project.inlang\\settings.json", JSON.stringify(settings));
|
|
98
178
|
const result = await tryCatch(() => loadProject({
|
|
99
|
-
|
|
179
|
+
projectPath: "C:\\Users\\user\\project.inlang",
|
|
100
180
|
nodeishFs: fs,
|
|
101
181
|
_import,
|
|
102
182
|
}));
|
|
@@ -108,7 +188,7 @@ describe("initialization", () => {
|
|
|
108
188
|
const fs = createNodeishMemoryFs();
|
|
109
189
|
fs.mkdir("/user/project", { recursive: true });
|
|
110
190
|
const project = await loadProject({
|
|
111
|
-
|
|
191
|
+
projectPath: "/user/non-existend-project.inlang",
|
|
112
192
|
nodeishFs: fs,
|
|
113
193
|
_import,
|
|
114
194
|
});
|
|
@@ -116,10 +196,10 @@ describe("initialization", () => {
|
|
|
116
196
|
});
|
|
117
197
|
it("should return an error if settings file is not a valid JSON", async () => {
|
|
118
198
|
const fs = await createNodeishMemoryFs();
|
|
119
|
-
await fs.mkdir("/user/project", { recursive: true });
|
|
120
|
-
await fs.writeFile("/user/project
|
|
199
|
+
await fs.mkdir("/user/project.inlang", { recursive: true });
|
|
200
|
+
await fs.writeFile("/user/project.inlang/settings.json", "invalid json");
|
|
121
201
|
const project = await loadProject({
|
|
122
|
-
|
|
202
|
+
projectPath: "/user/project.inlang",
|
|
123
203
|
nodeishFs: fs,
|
|
124
204
|
_import,
|
|
125
205
|
});
|
|
@@ -127,10 +207,10 @@ describe("initialization", () => {
|
|
|
127
207
|
});
|
|
128
208
|
it("should return an error if settings file is does not match schema", async () => {
|
|
129
209
|
const fs = await createNodeishMemoryFs();
|
|
130
|
-
await fs.mkdir("/user/project", { recursive: true });
|
|
131
|
-
await fs.writeFile("/user/project
|
|
210
|
+
await fs.mkdir("/user/project.inlang", { recursive: true });
|
|
211
|
+
await fs.writeFile("/user/project.inlang/settings.json", JSON.stringify({}));
|
|
132
212
|
const project = await loadProject({
|
|
133
|
-
|
|
213
|
+
projectPath: "/user/project.inlang",
|
|
134
214
|
nodeishFs: fs,
|
|
135
215
|
_import,
|
|
136
216
|
});
|
|
@@ -138,10 +218,10 @@ describe("initialization", () => {
|
|
|
138
218
|
});
|
|
139
219
|
it("should return the parsed settings", async () => {
|
|
140
220
|
const fs = await createNodeishMemoryFs();
|
|
141
|
-
await fs.mkdir("/user/project", { recursive: true });
|
|
142
|
-
await fs.writeFile("/user/project
|
|
221
|
+
await fs.mkdir("/user/project.inlang", { recursive: true });
|
|
222
|
+
await fs.writeFile("/user/project.inlang/settings.json", JSON.stringify(settings));
|
|
143
223
|
const project = await loadProject({
|
|
144
|
-
|
|
224
|
+
projectPath: "/user/project.inlang",
|
|
145
225
|
nodeishFs: fs,
|
|
146
226
|
_import,
|
|
147
227
|
});
|
|
@@ -150,21 +230,21 @@ describe("initialization", () => {
|
|
|
150
230
|
it("should not re-write the settings to disk when initializing", async () => {
|
|
151
231
|
const fs = await createNodeishMemoryFs();
|
|
152
232
|
const settingsWithDeifferentFormatting = JSON.stringify(settings, undefined, 4);
|
|
153
|
-
await fs.mkdir("/user/project", { recursive: true });
|
|
154
|
-
await fs.writeFile("/user/project
|
|
233
|
+
await fs.mkdir("/user/project.inlang", { recursive: true });
|
|
234
|
+
await fs.writeFile("/user/project.inlang/settings.json", settingsWithDeifferentFormatting);
|
|
155
235
|
const project = await loadProject({
|
|
156
|
-
|
|
236
|
+
projectPath: "/user/project.inlang",
|
|
157
237
|
nodeishFs: fs,
|
|
158
238
|
_import,
|
|
159
239
|
});
|
|
160
|
-
const settingsOnDisk = await fs.readFile("/user/project
|
|
240
|
+
const settingsOnDisk = await fs.readFile("/user/project.inlang/settings.json", {
|
|
161
241
|
encoding: "utf-8",
|
|
162
242
|
});
|
|
163
243
|
expect(settingsOnDisk).toBe(settingsWithDeifferentFormatting);
|
|
164
244
|
project.setSettings(project.settings());
|
|
165
245
|
// TODO: how can we await `setsettings` correctly
|
|
166
246
|
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
167
|
-
const newsettingsOnDisk = await fs.readFile("/user/project
|
|
247
|
+
const newsettingsOnDisk = await fs.readFile("/user/project.inlang/settings.json", {
|
|
168
248
|
encoding: "utf-8",
|
|
169
249
|
});
|
|
170
250
|
expect(newsettingsOnDisk).not.toBe(settingsWithDeifferentFormatting);
|
|
@@ -176,10 +256,10 @@ describe("initialization", () => {
|
|
|
176
256
|
default: {},
|
|
177
257
|
});
|
|
178
258
|
const fs = createNodeishMemoryFs();
|
|
179
|
-
await fs.mkdir("/user/project", { recursive: true });
|
|
180
|
-
await fs.writeFile("/user/project
|
|
259
|
+
await fs.mkdir("/user/project.inlang", { recursive: true });
|
|
260
|
+
await fs.writeFile("/user/project.inlang/settings.json", JSON.stringify(settings));
|
|
181
261
|
const project = await loadProject({
|
|
182
|
-
|
|
262
|
+
projectPath: "/user/project.inlang",
|
|
183
263
|
nodeishFs: fs,
|
|
184
264
|
_import: $badImport,
|
|
185
265
|
});
|
|
@@ -204,10 +284,10 @@ describe("functionality", () => {
|
|
|
204
284
|
describe("settings", () => {
|
|
205
285
|
it("should return the settings", async () => {
|
|
206
286
|
const fs = await createNodeishMemoryFs();
|
|
207
|
-
await fs.mkdir("/user/project", { recursive: true });
|
|
208
|
-
await fs.writeFile("/user/project
|
|
287
|
+
await fs.mkdir("/user/project.inlang", { recursive: true });
|
|
288
|
+
await fs.writeFile("/user/project.inlang/settings.json", JSON.stringify(settings));
|
|
209
289
|
const project = await loadProject({
|
|
210
|
-
|
|
290
|
+
projectPath: "/user/project.inlang",
|
|
211
291
|
nodeishFs: fs,
|
|
212
292
|
_import,
|
|
213
293
|
});
|
|
@@ -215,10 +295,10 @@ describe("functionality", () => {
|
|
|
215
295
|
});
|
|
216
296
|
it("should set a new settings", async () => {
|
|
217
297
|
const fs = await createNodeishMemoryFs();
|
|
218
|
-
await fs.mkdir("/user/project", { recursive: true });
|
|
219
|
-
await fs.writeFile("/user/project
|
|
298
|
+
await fs.mkdir("/user/project.inlang", { recursive: true });
|
|
299
|
+
await fs.writeFile("/user/project.inlang/settings.json", JSON.stringify(settings));
|
|
220
300
|
const project = await loadProject({
|
|
221
|
-
|
|
301
|
+
projectPath: "/user/project.inlang",
|
|
222
302
|
nodeishFs: fs,
|
|
223
303
|
_import,
|
|
224
304
|
});
|
|
@@ -235,12 +315,12 @@ describe("functionality", () => {
|
|
|
235
315
|
});
|
|
236
316
|
});
|
|
237
317
|
describe("setSettings", () => {
|
|
238
|
-
it("should fail if settings
|
|
318
|
+
it("should fail if settings are not valid", async () => {
|
|
239
319
|
const fs = await createNodeishMemoryFs();
|
|
240
|
-
await fs.mkdir("/user/project", { recursive: true });
|
|
241
|
-
await fs.writeFile("/user/project
|
|
320
|
+
await fs.mkdir("/user/project.inlang", { recursive: true });
|
|
321
|
+
await fs.writeFile("/user/project.inlang/settings.json", JSON.stringify(settings));
|
|
242
322
|
const project = await loadProject({
|
|
243
|
-
|
|
323
|
+
projectPath: "/user/project.inlang",
|
|
244
324
|
nodeishFs: fs,
|
|
245
325
|
_import,
|
|
246
326
|
});
|
|
@@ -250,15 +330,15 @@ describe("functionality", () => {
|
|
|
250
330
|
});
|
|
251
331
|
it("should throw an error if sourceLanguageTag is not in languageTags", async () => {
|
|
252
332
|
const fs = await createNodeishMemoryFs();
|
|
253
|
-
await fs.mkdir("/user/project", { recursive: true });
|
|
333
|
+
await fs.mkdir("/user/project.inlang", { recursive: true });
|
|
254
334
|
const settings = {
|
|
255
335
|
sourceLanguageTag: "en",
|
|
256
336
|
languageTags: ["de"],
|
|
257
337
|
modules: [],
|
|
258
338
|
};
|
|
259
|
-
await fs.writeFile("/user/project
|
|
339
|
+
await fs.writeFile("/user/project.inlang/settings.json", JSON.stringify(settings));
|
|
260
340
|
const project = await loadProject({
|
|
261
|
-
|
|
341
|
+
projectPath: "/user/project.inlang",
|
|
262
342
|
nodeishFs: fs,
|
|
263
343
|
_import,
|
|
264
344
|
});
|
|
@@ -267,21 +347,21 @@ describe("functionality", () => {
|
|
|
267
347
|
});
|
|
268
348
|
it("should write settings to disk", async () => {
|
|
269
349
|
const fs = await createNodeishMemoryFs();
|
|
270
|
-
await fs.mkdir("/user/project", { recursive: true });
|
|
271
|
-
await fs.writeFile("/user/project
|
|
350
|
+
await fs.mkdir("/user/project.inlang", { recursive: true });
|
|
351
|
+
await fs.writeFile("/user/project.inlang/settings.json", JSON.stringify(settings));
|
|
272
352
|
const project = await loadProject({
|
|
273
|
-
|
|
353
|
+
projectPath: "/user/project.inlang",
|
|
274
354
|
nodeishFs: fs,
|
|
275
355
|
_import,
|
|
276
356
|
});
|
|
277
|
-
const before = await fs.readFile("/user/project
|
|
357
|
+
const before = await fs.readFile("/user/project.inlang/settings.json", { encoding: "utf-8" });
|
|
278
358
|
expect(before).toBeDefined();
|
|
279
|
-
const result = project.setSettings({ ...settings, languageTags: ["en"] });
|
|
359
|
+
const result = project.setSettings({ ...settings, languageTags: ["en", "nl", "de"] });
|
|
280
360
|
expect(result.data).toBeUndefined();
|
|
281
361
|
expect(result.error).toBeUndefined();
|
|
282
362
|
// TODO: how to wait for fs.writeFile to finish?
|
|
283
|
-
await new Promise((resolve) => setTimeout(resolve,
|
|
284
|
-
const after = await fs.readFile("/user/project
|
|
363
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
364
|
+
const after = await fs.readFile("/user/project.inlang/settings.json", { encoding: "utf-8" });
|
|
285
365
|
expect(after).toBeDefined();
|
|
286
366
|
expect(after).not.toBe(before);
|
|
287
367
|
});
|
|
@@ -294,10 +374,10 @@ describe("functionality", () => {
|
|
|
294
374
|
languageTags: ["en"],
|
|
295
375
|
modules: ["plugin.js", "lintRule.js"],
|
|
296
376
|
};
|
|
297
|
-
await fs.mkdir("/user/project", { recursive: true });
|
|
298
|
-
await fs.writeFile("/user/project
|
|
377
|
+
await fs.mkdir("/user/project.inlang", { recursive: true });
|
|
378
|
+
await fs.writeFile("/user/project.inlang/settings.json", JSON.stringify(settings));
|
|
299
379
|
const project = await loadProject({
|
|
300
|
-
|
|
380
|
+
projectPath: "/user/project.inlang",
|
|
301
381
|
nodeishFs: fs,
|
|
302
382
|
_import,
|
|
303
383
|
});
|
|
@@ -322,10 +402,10 @@ describe("functionality", () => {
|
|
|
322
402
|
languageTags: ["en"],
|
|
323
403
|
modules: ["plugin.js", "lintRule.js"],
|
|
324
404
|
};
|
|
325
|
-
await fs.mkdir("/user/project", { recursive: true });
|
|
326
|
-
await fs.writeFile("/user/project
|
|
405
|
+
await fs.mkdir("/user/project.inlang", { recursive: true });
|
|
406
|
+
await fs.writeFile("/user/project.inlang/settings.json", JSON.stringify(settings));
|
|
327
407
|
const project = await loadProject({
|
|
328
|
-
|
|
408
|
+
projectPath: "/user/project.inlang",
|
|
329
409
|
nodeishFs: fs,
|
|
330
410
|
_import,
|
|
331
411
|
});
|
|
@@ -353,8 +433,8 @@ describe("functionality", () => {
|
|
|
353
433
|
saveMessages: () => undefined,
|
|
354
434
|
};
|
|
355
435
|
const fs = await createNodeishMemoryFs();
|
|
356
|
-
await fs.mkdir("/user/project", { recursive: true });
|
|
357
|
-
await fs.writeFile("/user/project
|
|
436
|
+
await fs.mkdir("/user/project.inlang", { recursive: true });
|
|
437
|
+
await fs.writeFile("/user/project.inlang/settings.json", JSON.stringify({
|
|
358
438
|
sourceLanguageTag: "en",
|
|
359
439
|
languageTags: ["en"],
|
|
360
440
|
modules: ["plugin.js", "lintRule.js"],
|
|
@@ -365,7 +445,7 @@ describe("functionality", () => {
|
|
|
365
445
|
};
|
|
366
446
|
};
|
|
367
447
|
const project = await loadProject({
|
|
368
|
-
|
|
448
|
+
projectPath: "/user/project.inlang",
|
|
369
449
|
nodeishFs: fs,
|
|
370
450
|
_import,
|
|
371
451
|
});
|
|
@@ -395,8 +475,8 @@ describe("functionality", () => {
|
|
|
395
475
|
saveMessages: () => undefined,
|
|
396
476
|
};
|
|
397
477
|
const fs = await createNodeishMemoryFs();
|
|
398
|
-
await fs.mkdir("/user/project", { recursive: true });
|
|
399
|
-
await fs.writeFile("/user/project
|
|
478
|
+
await fs.mkdir("/user/project.inlang", { recursive: true });
|
|
479
|
+
await fs.writeFile("/user/project.inlang/settings.json", JSON.stringify({
|
|
400
480
|
sourceLanguageTag: "en",
|
|
401
481
|
languageTags: ["en"],
|
|
402
482
|
modules: ["plugin.js", "lintRule.js"],
|
|
@@ -407,7 +487,7 @@ describe("functionality", () => {
|
|
|
407
487
|
};
|
|
408
488
|
};
|
|
409
489
|
const project = await loadProject({
|
|
410
|
-
|
|
490
|
+
projectPath: "/user/project.inlang",
|
|
411
491
|
nodeishFs: fs,
|
|
412
492
|
_import,
|
|
413
493
|
});
|
|
@@ -418,10 +498,10 @@ describe("functionality", () => {
|
|
|
418
498
|
describe("errors", () => {
|
|
419
499
|
it("should return the errors", async () => {
|
|
420
500
|
const fs = await createNodeishMemoryFs();
|
|
421
|
-
await fs.mkdir("/user/project", { recursive: true });
|
|
422
|
-
await fs.writeFile("/user/project
|
|
501
|
+
await fs.mkdir("/user/project.inlang", { recursive: true });
|
|
502
|
+
await fs.writeFile("/user/project.inlang/settings.json", JSON.stringify(settings));
|
|
423
503
|
const project = await loadProject({
|
|
424
|
-
|
|
504
|
+
projectPath: "/user/project.inlang",
|
|
425
505
|
nodeishFs: fs,
|
|
426
506
|
_import,
|
|
427
507
|
});
|
|
@@ -433,10 +513,10 @@ describe("functionality", () => {
|
|
|
433
513
|
describe("customApi", () => {
|
|
434
514
|
it("should return the app specific api", async () => {
|
|
435
515
|
const fs = await createNodeishMemoryFs();
|
|
436
|
-
await fs.mkdir("/user/project", { recursive: true });
|
|
437
|
-
await fs.writeFile("/user/project
|
|
516
|
+
await fs.mkdir("/user/project.inlang", { recursive: true });
|
|
517
|
+
await fs.writeFile("/user/project.inlang/settings.json", JSON.stringify(settings));
|
|
438
518
|
const project = await loadProject({
|
|
439
|
-
|
|
519
|
+
projectPath: "/user/project.inlang",
|
|
440
520
|
nodeishFs: fs,
|
|
441
521
|
_import,
|
|
442
522
|
});
|
|
@@ -448,10 +528,10 @@ describe("functionality", () => {
|
|
|
448
528
|
describe("messages", () => {
|
|
449
529
|
it("should return the messages", async () => {
|
|
450
530
|
const fs = await createNodeishMemoryFs();
|
|
451
|
-
await fs.mkdir("/user/project", { recursive: true });
|
|
452
|
-
await fs.writeFile("/user/project
|
|
531
|
+
await fs.mkdir("/user/project.inlang", { recursive: true });
|
|
532
|
+
await fs.writeFile("/user/project.inlang/settings.json", JSON.stringify(settings));
|
|
453
533
|
const project = await loadProject({
|
|
454
|
-
|
|
534
|
+
projectPath: "/user/project.inlang",
|
|
455
535
|
nodeishFs: fs,
|
|
456
536
|
_import,
|
|
457
537
|
});
|
|
@@ -469,8 +549,8 @@ describe("functionality", () => {
|
|
|
469
549
|
pathPattern: "./resources/{languageTag}.json",
|
|
470
550
|
},
|
|
471
551
|
};
|
|
472
|
-
await fs.mkdir("/user/project", { recursive: true });
|
|
473
|
-
await fs.writeFile("/user/project
|
|
552
|
+
await fs.mkdir("/user/project.inlang", { recursive: true });
|
|
553
|
+
await fs.writeFile("/user/project.inlang/settings.json", JSON.stringify(settings));
|
|
474
554
|
await fs.mkdir("./resources");
|
|
475
555
|
const mockSaveFn = vi.fn();
|
|
476
556
|
const _mockPlugin = {
|
|
@@ -486,7 +566,7 @@ describe("functionality", () => {
|
|
|
486
566
|
};
|
|
487
567
|
};
|
|
488
568
|
const project = await loadProject({
|
|
489
|
-
|
|
569
|
+
projectPath: "/user/project.inlang",
|
|
490
570
|
nodeishFs: fs,
|
|
491
571
|
_import,
|
|
492
572
|
});
|
|
@@ -631,7 +711,8 @@ describe("functionality", () => {
|
|
|
631
711
|
pathPattern: "./resources/{languageTag}.json",
|
|
632
712
|
},
|
|
633
713
|
};
|
|
634
|
-
await fs.
|
|
714
|
+
await fs.mkdir("./project.inlang", { recursive: true });
|
|
715
|
+
await fs.writeFile("./project.inlang/settings.json", JSON.stringify(settings));
|
|
635
716
|
const mockSaveFn = vi.fn();
|
|
636
717
|
const _mockPlugin = {
|
|
637
718
|
id: "plugin.placeholder.name",
|
|
@@ -650,7 +731,7 @@ describe("functionality", () => {
|
|
|
650
731
|
};
|
|
651
732
|
};
|
|
652
733
|
const project = await loadProject({
|
|
653
|
-
|
|
734
|
+
projectPath: "/project.inlang",
|
|
654
735
|
nodeishFs: fs,
|
|
655
736
|
_import,
|
|
656
737
|
});
|
|
@@ -666,7 +747,7 @@ describe("functionality", () => {
|
|
|
666
747
|
await fs.mkdir("/user/project", { recursive: true });
|
|
667
748
|
await fs.writeFile("/user/project/project.inlang.json", JSON.stringify(settings));
|
|
668
749
|
const project = await loadProject({
|
|
669
|
-
|
|
750
|
+
projectPath: "/user/project/project.inlang.json",
|
|
670
751
|
nodeishFs: fs,
|
|
671
752
|
_import,
|
|
672
753
|
});
|
|
@@ -686,10 +767,10 @@ describe("functionality", () => {
|
|
|
686
767
|
modules: ["lintRule.js"],
|
|
687
768
|
};
|
|
688
769
|
const fs = createNodeishMemoryFs();
|
|
689
|
-
await fs.mkdir("/user/project", { recursive: true });
|
|
690
|
-
await fs.writeFile("/user/project
|
|
770
|
+
await fs.mkdir("/user/project.inlang", { recursive: true });
|
|
771
|
+
await fs.writeFile("/user/project.inlang/settings.json", JSON.stringify(settings));
|
|
691
772
|
const project = await loadProject({
|
|
692
|
-
|
|
773
|
+
projectPath: "/user/project.inlang",
|
|
693
774
|
nodeishFs: fs,
|
|
694
775
|
_import: async () => ({
|
|
695
776
|
default: mockMessageLintRule,
|
|
@@ -743,10 +824,11 @@ describe("functionality", () => {
|
|
|
743
824
|
filePath: "./messages.json",
|
|
744
825
|
},
|
|
745
826
|
};
|
|
746
|
-
await fs.
|
|
827
|
+
await fs.mkdir("./project.inlang", { recursive: true });
|
|
828
|
+
await fs.writeFile("./project.inlang/settings.json", JSON.stringify(settings));
|
|
747
829
|
// establish watcher
|
|
748
830
|
const project = await loadProject({
|
|
749
|
-
|
|
831
|
+
projectPath: normalizePath("/project.inlang"),
|
|
750
832
|
nodeishFs: fs,
|
|
751
833
|
_import: async () => ({
|
|
752
834
|
default: mockMessageFormatPlugin,
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { NodeishFilesystem } from "@lix-js/fs";
|
|
2
|
+
/**
|
|
3
|
+
* Migrates to the new project directory structure
|
|
4
|
+
* https://github.com/inlang/monorepo/issues/1678
|
|
5
|
+
*/
|
|
6
|
+
export declare const maybeMigrateToDirectory: (args: {
|
|
7
|
+
nodeishFs: NodeishFilesystem;
|
|
8
|
+
projectPath: string;
|
|
9
|
+
}) => Promise<void>;
|
|
10
|
+
//# sourceMappingURL=migrateToDirectory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migrateToDirectory.d.ts","sourceRoot":"","sources":["../../src/migrations/migrateToDirectory.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AAEnD;;;GAGG;AACH,eAAO,MAAM,uBAAuB,SAAgB;IACnD,SAAS,EAAE,iBAAiB,CAAA;IAC5B,WAAW,EAAE,MAAM,CAAA;CACnB,kBA0BA,CAAA"}
|