@inlang/sdk 0.22.0 → 0.24.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 +2 -2
- package/dist/adapter/solidAdapter.test.js +13 -6
- package/dist/createNodeishFsWithWatcher.js +1 -1
- package/dist/env-variables/index.d.ts +4 -0
- package/dist/env-variables/index.d.ts.map +1 -0
- package/dist/env-variables/index.js +3 -0
- package/dist/listProjects.d.ts.map +1 -1
- package/dist/listProjects.js +15 -9
- package/dist/listProjects.test.js +14 -1
- package/dist/loadProject.d.ts +28 -9
- package/dist/loadProject.d.ts.map +1 -1
- package/dist/loadProject.js +49 -50
- package/dist/loadProject.test.js +70 -33
- package/dist/migrations/maybeCreateFirstProjectId.d.ts +16 -0
- package/dist/migrations/maybeCreateFirstProjectId.d.ts.map +1 -0
- package/dist/migrations/maybeCreateFirstProjectId.js +37 -0
- package/dist/migrations/maybeCreateFirstProjectId.test.d.ts +2 -0
- package/dist/migrations/maybeCreateFirstProjectId.test.d.ts.map +1 -0
- package/dist/migrations/maybeCreateFirstProjectId.test.js +27 -0
- package/dist/migrations/migrateToDirectory.d.ts +1 -1
- package/dist/migrations/migrateToDirectory.js +3 -3
- package/dist/telemetry/capture.d.ts +21 -0
- package/dist/telemetry/capture.d.ts.map +1 -0
- package/dist/telemetry/capture.js +39 -0
- package/package.json +13 -12
- package/src/adapter/solidAdapter.test.ts +13 -6
- package/src/createNodeishFsWithWatcher.ts +1 -1
- package/src/env-variables/.prettierignore +1 -0
- package/src/env-variables/createIndexFile.js +28 -0
- package/src/env-variables/index.d.ts +13 -0
- package/src/listProjects.test.ts +21 -2
- package/src/listProjects.ts +14 -7
- package/src/loadProject.test.ts +73 -33
- package/src/loadProject.ts +91 -48
- package/src/migrations/maybeCreateFirstProjectId.test.ts +34 -0
- package/src/migrations/maybeCreateFirstProjectId.ts +43 -0
- package/src/migrations/migrateToDirectory.ts +3 -3
- package/src/telemetry/capture.ts +49 -0
- package/dist/generateProjectId.d.ts +0 -3
- package/dist/generateProjectId.d.ts.map +0 -1
- package/dist/generateProjectId.js +0 -11
- package/dist/generateProjectId.test.d.ts +0 -2
- package/dist/generateProjectId.test.d.ts.map +0 -1
- package/dist/generateProjectId.test.js +0 -18
- package/src/generateProjectId.test.ts +0 -22
- package/src/generateProjectId.ts +0 -14
package/dist/loadProject.test.js
CHANGED
|
@@ -5,7 +5,12 @@ 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
|
+
import { mockRepo, openRepository } from "@lix-js/client";
|
|
9
|
+
import {} from "@lix-js/fs";
|
|
10
|
+
// eslint-disable-next-line no-restricted-imports -- test
|
|
11
|
+
import { readFileSync } from "node:fs";
|
|
12
|
+
// eslint-disable-next-line no-restricted-imports -- test
|
|
13
|
+
import { resolve } from "node:path";
|
|
9
14
|
// ------------------------------------------------------------------------------------------------
|
|
10
15
|
const getValue = (subscribable) => {
|
|
11
16
|
let value;
|
|
@@ -80,6 +85,13 @@ const mockMessageLintRule = {
|
|
|
80
85
|
const _import = async (name) => ({
|
|
81
86
|
default: name === "plugin.js" ? mockPlugin : mockMessageLintRule,
|
|
82
87
|
});
|
|
88
|
+
async function openCiTestRepo() {
|
|
89
|
+
return await mockRepo({
|
|
90
|
+
fromSnapshot: JSON.parse(readFileSync(resolve(__dirname, "../mocks/ci-test-repo-no-shallow.json"), {
|
|
91
|
+
encoding: "utf-8",
|
|
92
|
+
})),
|
|
93
|
+
});
|
|
94
|
+
}
|
|
83
95
|
// ------------------------------------------------------------------------------------------------
|
|
84
96
|
/**
|
|
85
97
|
* Dear Developers,
|
|
@@ -89,15 +101,17 @@ const _import = async (name) => ({
|
|
|
89
101
|
*/
|
|
90
102
|
it("should throw if a project (path) does not have a name", async () => {
|
|
91
103
|
const fs = createNodeishMemoryFs();
|
|
104
|
+
const repo = await openRepository("file://", { nodeishFs: fs });
|
|
92
105
|
const project = await tryCatch(() => loadProject({
|
|
93
106
|
projectPath: "/source-code/.inlang",
|
|
94
|
-
|
|
107
|
+
repo,
|
|
95
108
|
_import,
|
|
96
109
|
}));
|
|
97
110
|
expect(project.error).toBeInstanceOf(LoadProjectInvalidArgument);
|
|
98
111
|
});
|
|
99
112
|
it("should throw if a project path does not end with .inlang", async () => {
|
|
100
113
|
const fs = createNodeishMemoryFs();
|
|
114
|
+
const repo = await openRepository("file://", { nodeishFs: fs });
|
|
101
115
|
const invalidPaths = [
|
|
102
116
|
"/source-code/frontend.inlang/settings",
|
|
103
117
|
"/source-code/frontend.inlang/settings.json",
|
|
@@ -106,7 +120,7 @@ it("should throw if a project path does not end with .inlang", async () => {
|
|
|
106
120
|
for (const invalidPath of invalidPaths) {
|
|
107
121
|
const project = await tryCatch(() => loadProject({
|
|
108
122
|
projectPath: invalidPath,
|
|
109
|
-
|
|
123
|
+
repo,
|
|
110
124
|
_import,
|
|
111
125
|
}));
|
|
112
126
|
expect(project.error).toBeInstanceOf(LoadProjectInvalidArgument);
|
|
@@ -115,16 +129,17 @@ it("should throw if a project path does not end with .inlang", async () => {
|
|
|
115
129
|
describe("initialization", () => {
|
|
116
130
|
it("should throw if projectPath is not an absolute path", async () => {
|
|
117
131
|
const fs = createNodeishMemoryFs();
|
|
132
|
+
const repo = await openRepository("file://", { nodeishFs: fs });
|
|
118
133
|
const result = await tryCatch(() => loadProject({
|
|
119
134
|
projectPath: "relative/path",
|
|
120
|
-
|
|
135
|
+
repo,
|
|
121
136
|
_import,
|
|
122
137
|
}));
|
|
123
138
|
expect(result.error).toBeInstanceOf(LoadProjectInvalidArgument);
|
|
124
139
|
expect(result.data).toBeUndefined();
|
|
125
140
|
});
|
|
126
141
|
it("should generate projectId on missing projectid", async () => {
|
|
127
|
-
const repo = await
|
|
142
|
+
const repo = await openCiTestRepo();
|
|
128
143
|
const existing = await repo.nodeishFs
|
|
129
144
|
.readFile("/project.inlang/project_id", {
|
|
130
145
|
encoding: "utf-8",
|
|
@@ -136,7 +151,6 @@ describe("initialization", () => {
|
|
|
136
151
|
expect(existing.error.code).toBe("ENOENT");
|
|
137
152
|
const result = await tryCatch(() => loadProject({
|
|
138
153
|
projectPath: "/project.inlang",
|
|
139
|
-
nodeishFs: repo.nodeishFs,
|
|
140
154
|
repo,
|
|
141
155
|
_import,
|
|
142
156
|
}));
|
|
@@ -147,16 +161,15 @@ describe("initialization", () => {
|
|
|
147
161
|
.catch((error) => {
|
|
148
162
|
return { error };
|
|
149
163
|
});
|
|
150
|
-
expect(newId).toBe("
|
|
164
|
+
expect(newId).toBe("aef225403be8b526dfb492a4617fd59d8181e8fef2c7f4aff56ab299046e36ed");
|
|
151
165
|
expect(result.error).toBeUndefined();
|
|
152
166
|
expect(result.data).toBeDefined();
|
|
153
167
|
});
|
|
154
168
|
it("should reuse projectId on existing projectid", async () => {
|
|
155
|
-
const repo = await
|
|
169
|
+
const repo = await openCiTestRepo();
|
|
156
170
|
repo.nodeishFs.writeFile("/project.inlang/project_id", "testId");
|
|
157
171
|
const result = await tryCatch(() => loadProject({
|
|
158
172
|
projectPath: "/project.inlang",
|
|
159
|
-
nodeishFs: repo.nodeishFs,
|
|
160
173
|
repo,
|
|
161
174
|
_import,
|
|
162
175
|
}));
|
|
@@ -175,9 +188,10 @@ describe("initialization", () => {
|
|
|
175
188
|
const fs = createNodeishMemoryFs();
|
|
176
189
|
fs.mkdir("C:\\Users\\user\\project.inlang", { recursive: true });
|
|
177
190
|
fs.writeFile("C:\\Users\\user\\project.inlang\\settings.json", JSON.stringify(settings));
|
|
191
|
+
const repo = await openRepository("file://", { nodeishFs: fs });
|
|
178
192
|
const result = await tryCatch(() => loadProject({
|
|
179
193
|
projectPath: "C:\\Users\\user\\project.inlang",
|
|
180
|
-
|
|
194
|
+
repo,
|
|
181
195
|
_import,
|
|
182
196
|
}));
|
|
183
197
|
expect(result.error).toBeUndefined();
|
|
@@ -187,9 +201,10 @@ describe("initialization", () => {
|
|
|
187
201
|
it("should return an error if settings file is not found", async () => {
|
|
188
202
|
const fs = createNodeishMemoryFs();
|
|
189
203
|
fs.mkdir("/user/project", { recursive: true });
|
|
204
|
+
const repo = await openRepository("file://", { nodeishFs: fs });
|
|
190
205
|
const project = await loadProject({
|
|
191
206
|
projectPath: "/user/non-existend-project.inlang",
|
|
192
|
-
|
|
207
|
+
repo,
|
|
193
208
|
_import,
|
|
194
209
|
});
|
|
195
210
|
expect(project.errors()[0]).toBeInstanceOf(ProjectSettingsFileNotFoundError);
|
|
@@ -198,9 +213,10 @@ describe("initialization", () => {
|
|
|
198
213
|
const fs = await createNodeishMemoryFs();
|
|
199
214
|
await fs.mkdir("/user/project.inlang", { recursive: true });
|
|
200
215
|
await fs.writeFile("/user/project.inlang/settings.json", "invalid json");
|
|
216
|
+
const repo = await openRepository("file://", { nodeishFs: fs });
|
|
201
217
|
const project = await loadProject({
|
|
202
218
|
projectPath: "/user/project.inlang",
|
|
203
|
-
|
|
219
|
+
repo,
|
|
204
220
|
_import,
|
|
205
221
|
});
|
|
206
222
|
expect(project.errors()[0]).toBeInstanceOf(ProjectSettingsFileJSONSyntaxError);
|
|
@@ -209,9 +225,10 @@ describe("initialization", () => {
|
|
|
209
225
|
const fs = await createNodeishMemoryFs();
|
|
210
226
|
await fs.mkdir("/user/project.inlang", { recursive: true });
|
|
211
227
|
await fs.writeFile("/user/project.inlang/settings.json", JSON.stringify({}));
|
|
228
|
+
const repo = await openRepository("file://", { nodeishFs: fs });
|
|
212
229
|
const project = await loadProject({
|
|
213
230
|
projectPath: "/user/project.inlang",
|
|
214
|
-
|
|
231
|
+
repo,
|
|
215
232
|
_import,
|
|
216
233
|
});
|
|
217
234
|
expect(project.errors()[0]).toBeInstanceOf(ProjectSettingsInvalidError);
|
|
@@ -220,9 +237,10 @@ describe("initialization", () => {
|
|
|
220
237
|
const fs = await createNodeishMemoryFs();
|
|
221
238
|
await fs.mkdir("/user/project.inlang", { recursive: true });
|
|
222
239
|
await fs.writeFile("/user/project.inlang/settings.json", JSON.stringify(settings));
|
|
240
|
+
const repo = await openRepository("file://", { nodeishFs: fs });
|
|
223
241
|
const project = await loadProject({
|
|
224
242
|
projectPath: "/user/project.inlang",
|
|
225
|
-
|
|
243
|
+
repo,
|
|
226
244
|
_import,
|
|
227
245
|
});
|
|
228
246
|
expect(project.settings()).toStrictEqual(settings);
|
|
@@ -232,9 +250,10 @@ describe("initialization", () => {
|
|
|
232
250
|
const settingsWithDeifferentFormatting = JSON.stringify(settings, undefined, 4);
|
|
233
251
|
await fs.mkdir("/user/project.inlang", { recursive: true });
|
|
234
252
|
await fs.writeFile("/user/project.inlang/settings.json", settingsWithDeifferentFormatting);
|
|
253
|
+
const repo = await openRepository("file://", { nodeishFs: fs });
|
|
235
254
|
const project = await loadProject({
|
|
236
255
|
projectPath: "/user/project.inlang",
|
|
237
|
-
|
|
256
|
+
repo,
|
|
238
257
|
_import,
|
|
239
258
|
});
|
|
240
259
|
const settingsOnDisk = await fs.readFile("/user/project.inlang/settings.json", {
|
|
@@ -258,9 +277,10 @@ describe("initialization", () => {
|
|
|
258
277
|
const fs = createNodeishMemoryFs();
|
|
259
278
|
await fs.mkdir("/user/project.inlang", { recursive: true });
|
|
260
279
|
await fs.writeFile("/user/project.inlang/settings.json", JSON.stringify(settings));
|
|
280
|
+
const repo = await openRepository("file://", { nodeishFs: fs });
|
|
261
281
|
const project = await loadProject({
|
|
262
282
|
projectPath: "/user/project.inlang",
|
|
263
|
-
|
|
283
|
+
repo,
|
|
264
284
|
_import: $badImport,
|
|
265
285
|
});
|
|
266
286
|
expect(project.errors()).not.toHaveLength(0);
|
|
@@ -286,9 +306,10 @@ describe("functionality", () => {
|
|
|
286
306
|
const fs = await createNodeishMemoryFs();
|
|
287
307
|
await fs.mkdir("/user/project.inlang", { recursive: true });
|
|
288
308
|
await fs.writeFile("/user/project.inlang/settings.json", JSON.stringify(settings));
|
|
309
|
+
const repo = await openRepository("file://", { nodeishFs: fs });
|
|
289
310
|
const project = await loadProject({
|
|
290
311
|
projectPath: "/user/project.inlang",
|
|
291
|
-
|
|
312
|
+
repo,
|
|
292
313
|
_import,
|
|
293
314
|
});
|
|
294
315
|
expect(getValue(project.settings)).toStrictEqual(settings);
|
|
@@ -297,9 +318,10 @@ describe("functionality", () => {
|
|
|
297
318
|
const fs = await createNodeishMemoryFs();
|
|
298
319
|
await fs.mkdir("/user/project.inlang", { recursive: true });
|
|
299
320
|
await fs.writeFile("/user/project.inlang/settings.json", JSON.stringify(settings));
|
|
321
|
+
const repo = await openRepository("file://", { nodeishFs: fs });
|
|
300
322
|
const project = await loadProject({
|
|
301
323
|
projectPath: "/user/project.inlang",
|
|
302
|
-
|
|
324
|
+
repo,
|
|
303
325
|
_import,
|
|
304
326
|
});
|
|
305
327
|
expect(project.settings()).toStrictEqual(settings);
|
|
@@ -319,9 +341,10 @@ describe("functionality", () => {
|
|
|
319
341
|
const fs = await createNodeishMemoryFs();
|
|
320
342
|
await fs.mkdir("/user/project.inlang", { recursive: true });
|
|
321
343
|
await fs.writeFile("/user/project.inlang/settings.json", JSON.stringify(settings));
|
|
344
|
+
const repo = await openRepository("file://", { nodeishFs: fs });
|
|
322
345
|
const project = await loadProject({
|
|
323
346
|
projectPath: "/user/project.inlang",
|
|
324
|
-
|
|
347
|
+
repo,
|
|
325
348
|
_import,
|
|
326
349
|
});
|
|
327
350
|
const result = project.setSettings({});
|
|
@@ -337,9 +360,10 @@ describe("functionality", () => {
|
|
|
337
360
|
modules: [],
|
|
338
361
|
};
|
|
339
362
|
await fs.writeFile("/user/project.inlang/settings.json", JSON.stringify(settings));
|
|
363
|
+
const repo = await openRepository("file://", { nodeishFs: fs });
|
|
340
364
|
const project = await loadProject({
|
|
341
365
|
projectPath: "/user/project.inlang",
|
|
342
|
-
|
|
366
|
+
repo,
|
|
343
367
|
_import,
|
|
344
368
|
});
|
|
345
369
|
expect(project.errors()).toHaveLength(1);
|
|
@@ -349,9 +373,10 @@ describe("functionality", () => {
|
|
|
349
373
|
const fs = await createNodeishMemoryFs();
|
|
350
374
|
await fs.mkdir("/user/project.inlang", { recursive: true });
|
|
351
375
|
await fs.writeFile("/user/project.inlang/settings.json", JSON.stringify(settings));
|
|
376
|
+
const repo = await openRepository("file://", { nodeishFs: fs });
|
|
352
377
|
const project = await loadProject({
|
|
353
378
|
projectPath: "/user/project.inlang",
|
|
354
|
-
|
|
379
|
+
repo,
|
|
355
380
|
_import,
|
|
356
381
|
});
|
|
357
382
|
const before = await fs.readFile("/user/project.inlang/settings.json", { encoding: "utf-8" });
|
|
@@ -376,9 +401,10 @@ describe("functionality", () => {
|
|
|
376
401
|
};
|
|
377
402
|
await fs.mkdir("/user/project.inlang", { recursive: true });
|
|
378
403
|
await fs.writeFile("/user/project.inlang/settings.json", JSON.stringify(settings));
|
|
404
|
+
const repo = await openRepository("file://", { nodeishFs: fs });
|
|
379
405
|
const project = await loadProject({
|
|
380
406
|
projectPath: "/user/project.inlang",
|
|
381
|
-
|
|
407
|
+
repo,
|
|
382
408
|
_import,
|
|
383
409
|
});
|
|
384
410
|
expect(project.installed.plugins()[0]).toStrictEqual({
|
|
@@ -404,9 +430,10 @@ describe("functionality", () => {
|
|
|
404
430
|
};
|
|
405
431
|
await fs.mkdir("/user/project.inlang", { recursive: true });
|
|
406
432
|
await fs.writeFile("/user/project.inlang/settings.json", JSON.stringify(settings));
|
|
433
|
+
const repo = await openRepository("file://", { nodeishFs: fs });
|
|
407
434
|
const project = await loadProject({
|
|
408
435
|
projectPath: "/user/project.inlang",
|
|
409
|
-
|
|
436
|
+
repo,
|
|
410
437
|
_import,
|
|
411
438
|
});
|
|
412
439
|
expect(project.installed.messageLintRules()[0]?.level).toBe("warning");
|
|
@@ -439,6 +466,7 @@ describe("functionality", () => {
|
|
|
439
466
|
languageTags: ["en"],
|
|
440
467
|
modules: ["plugin.js", "lintRule.js"],
|
|
441
468
|
}));
|
|
469
|
+
const repo = await openRepository("file://", { nodeishFs: fs });
|
|
442
470
|
const _import = async (name) => {
|
|
443
471
|
return {
|
|
444
472
|
default: name === "plugin.js" ? _mockPlugin : _mockLintRule,
|
|
@@ -446,7 +474,7 @@ describe("functionality", () => {
|
|
|
446
474
|
};
|
|
447
475
|
const project = await loadProject({
|
|
448
476
|
projectPath: "/user/project.inlang",
|
|
449
|
-
|
|
477
|
+
repo,
|
|
450
478
|
_import,
|
|
451
479
|
});
|
|
452
480
|
await new Promise((resolve) => setTimeout(resolve, 510));
|
|
@@ -481,6 +509,7 @@ describe("functionality", () => {
|
|
|
481
509
|
languageTags: ["en"],
|
|
482
510
|
modules: ["plugin.js", "lintRule.js"],
|
|
483
511
|
}));
|
|
512
|
+
const repo = await openRepository("file://", { nodeishFs: fs });
|
|
484
513
|
const _import = async (name) => {
|
|
485
514
|
return {
|
|
486
515
|
default: name === "plugin.js" ? _mockPlugin : _mockLintRule,
|
|
@@ -488,7 +517,7 @@ describe("functionality", () => {
|
|
|
488
517
|
};
|
|
489
518
|
const project = await loadProject({
|
|
490
519
|
projectPath: "/user/project.inlang",
|
|
491
|
-
|
|
520
|
+
repo,
|
|
492
521
|
_import,
|
|
493
522
|
});
|
|
494
523
|
await new Promise((resolve) => setTimeout(resolve, 510));
|
|
@@ -500,9 +529,10 @@ describe("functionality", () => {
|
|
|
500
529
|
const fs = await createNodeishMemoryFs();
|
|
501
530
|
await fs.mkdir("/user/project.inlang", { recursive: true });
|
|
502
531
|
await fs.writeFile("/user/project.inlang/settings.json", JSON.stringify(settings));
|
|
532
|
+
const repo = await openRepository("file://", { nodeishFs: fs });
|
|
503
533
|
const project = await loadProject({
|
|
504
534
|
projectPath: "/user/project.inlang",
|
|
505
|
-
|
|
535
|
+
repo,
|
|
506
536
|
_import,
|
|
507
537
|
});
|
|
508
538
|
project.errors.subscribe((errors) => {
|
|
@@ -515,9 +545,10 @@ describe("functionality", () => {
|
|
|
515
545
|
const fs = await createNodeishMemoryFs();
|
|
516
546
|
await fs.mkdir("/user/project.inlang", { recursive: true });
|
|
517
547
|
await fs.writeFile("/user/project.inlang/settings.json", JSON.stringify(settings));
|
|
548
|
+
const repo = await openRepository("file://", { nodeishFs: fs });
|
|
518
549
|
const project = await loadProject({
|
|
519
550
|
projectPath: "/user/project.inlang",
|
|
520
|
-
|
|
551
|
+
repo,
|
|
521
552
|
_import,
|
|
522
553
|
});
|
|
523
554
|
project.customApi.subscribe((api) => {
|
|
@@ -530,9 +561,10 @@ describe("functionality", () => {
|
|
|
530
561
|
const fs = await createNodeishMemoryFs();
|
|
531
562
|
await fs.mkdir("/user/project.inlang", { recursive: true });
|
|
532
563
|
await fs.writeFile("/user/project.inlang/settings.json", JSON.stringify(settings));
|
|
564
|
+
const repo = await openRepository("file://", { nodeishFs: fs });
|
|
533
565
|
const project = await loadProject({
|
|
534
566
|
projectPath: "/user/project.inlang",
|
|
535
|
-
|
|
567
|
+
repo,
|
|
536
568
|
_import,
|
|
537
569
|
});
|
|
538
570
|
expect(Object.values(project.query.messages.getAll())).toEqual(exampleMessages);
|
|
@@ -552,6 +584,7 @@ describe("functionality", () => {
|
|
|
552
584
|
await fs.mkdir("/user/project.inlang", { recursive: true });
|
|
553
585
|
await fs.writeFile("/user/project.inlang/settings.json", JSON.stringify(settings));
|
|
554
586
|
await fs.mkdir("./resources");
|
|
587
|
+
const repo = await openRepository("file://", { nodeishFs: fs });
|
|
555
588
|
const mockSaveFn = vi.fn();
|
|
556
589
|
const _mockPlugin = {
|
|
557
590
|
id: "plugin.project.json",
|
|
@@ -567,7 +600,7 @@ describe("functionality", () => {
|
|
|
567
600
|
};
|
|
568
601
|
const project = await loadProject({
|
|
569
602
|
projectPath: "/user/project.inlang",
|
|
570
|
-
|
|
603
|
+
repo,
|
|
571
604
|
_import,
|
|
572
605
|
});
|
|
573
606
|
await project.query.messages.upsert({
|
|
@@ -713,6 +746,7 @@ describe("functionality", () => {
|
|
|
713
746
|
};
|
|
714
747
|
await fs.mkdir("./project.inlang", { recursive: true });
|
|
715
748
|
await fs.writeFile("./project.inlang/settings.json", JSON.stringify(settings));
|
|
749
|
+
const repo = await openRepository("file://", { nodeishFs: fs });
|
|
716
750
|
const mockSaveFn = vi.fn();
|
|
717
751
|
const _mockPlugin = {
|
|
718
752
|
id: "plugin.placeholder.name",
|
|
@@ -732,7 +766,7 @@ describe("functionality", () => {
|
|
|
732
766
|
};
|
|
733
767
|
const project = await loadProject({
|
|
734
768
|
projectPath: "/project.inlang",
|
|
735
|
-
|
|
769
|
+
repo,
|
|
736
770
|
_import,
|
|
737
771
|
});
|
|
738
772
|
project.query.messages.create({ data: createMessage("fourth", { en: "fourth message" }) });
|
|
@@ -746,9 +780,10 @@ describe("functionality", () => {
|
|
|
746
780
|
const fs = await createNodeishMemoryFs();
|
|
747
781
|
await fs.mkdir("/user/project", { recursive: true });
|
|
748
782
|
await fs.writeFile("/user/project/project.inlang.json", JSON.stringify(settings));
|
|
783
|
+
const repo = await openRepository("file://", { nodeishFs: fs });
|
|
749
784
|
const project = await loadProject({
|
|
750
785
|
projectPath: "/user/project/project.inlang.json",
|
|
751
|
-
|
|
786
|
+
repo,
|
|
752
787
|
_import,
|
|
753
788
|
});
|
|
754
789
|
// TODO: test with real lint rules
|
|
@@ -769,9 +804,10 @@ describe("functionality", () => {
|
|
|
769
804
|
const fs = createNodeishMemoryFs();
|
|
770
805
|
await fs.mkdir("/user/project.inlang", { recursive: true });
|
|
771
806
|
await fs.writeFile("/user/project.inlang/settings.json", JSON.stringify(settings));
|
|
807
|
+
const repo = await openRepository("file://", { nodeishFs: fs });
|
|
772
808
|
const project = await loadProject({
|
|
773
809
|
projectPath: "/user/project.inlang",
|
|
774
|
-
|
|
810
|
+
repo,
|
|
775
811
|
_import: async () => ({
|
|
776
812
|
default: mockMessageLintRule,
|
|
777
813
|
}),
|
|
@@ -826,10 +862,11 @@ describe("functionality", () => {
|
|
|
826
862
|
};
|
|
827
863
|
await fs.mkdir("./project.inlang", { recursive: true });
|
|
828
864
|
await fs.writeFile("./project.inlang/settings.json", JSON.stringify(settings));
|
|
865
|
+
const repo = await openRepository("file://", { nodeishFs: fs });
|
|
829
866
|
// establish watcher
|
|
830
867
|
const project = await loadProject({
|
|
831
868
|
projectPath: normalizePath("/project.inlang"),
|
|
832
|
-
|
|
869
|
+
repo,
|
|
833
870
|
_import: async () => ({
|
|
834
871
|
default: mockMessageFormatPlugin,
|
|
835
872
|
}),
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Repository } from "@lix-js/client";
|
|
2
|
+
/**
|
|
3
|
+
* Creates a project id if it does not exist yet.
|
|
4
|
+
*
|
|
5
|
+
* - this is a migration to ensure that all projects have a project id
|
|
6
|
+
* - new projects are created with a project id (in the future)
|
|
7
|
+
*/
|
|
8
|
+
export declare function maybeCreateFirstProjectId(args: {
|
|
9
|
+
projectPath: string;
|
|
10
|
+
repo?: Repository;
|
|
11
|
+
}): Promise<void>;
|
|
12
|
+
export declare function generateProjectId(args: {
|
|
13
|
+
repo?: Repository;
|
|
14
|
+
projectPath: string;
|
|
15
|
+
}): Promise<string | undefined>;
|
|
16
|
+
//# sourceMappingURL=maybeCreateFirstProjectId.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"maybeCreateFirstProjectId.d.ts","sourceRoot":"","sources":["../../src/migrations/maybeCreateFirstProjectId.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAGhD;;;;;GAKG;AACH,wBAAsB,yBAAyB,CAAC,IAAI,EAAE;IACrD,WAAW,EAAE,MAAM,CAAA;IACnB,IAAI,CAAC,EAAE,UAAU,CAAA;CACjB,GAAG,OAAO,CAAC,IAAI,CAAC,CAkBhB;AAED,wBAAsB,iBAAiB,CAAC,IAAI,EAAE;IAAE,IAAI,CAAC,EAAE,UAAU,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,+BAUvF"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { hash } from "@lix-js/client";
|
|
2
|
+
/**
|
|
3
|
+
* Creates a project id if it does not exist yet.
|
|
4
|
+
*
|
|
5
|
+
* - this is a migration to ensure that all projects have a project id
|
|
6
|
+
* - new projects are created with a project id (in the future)
|
|
7
|
+
*/
|
|
8
|
+
export async function maybeCreateFirstProjectId(args) {
|
|
9
|
+
// the migration assumes a repository
|
|
10
|
+
if (args.repo === undefined) {
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
try {
|
|
14
|
+
await args.repo.nodeishFs.readFile(args.projectPath + "/project_id", {
|
|
15
|
+
encoding: "utf-8",
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
catch (error) {
|
|
19
|
+
// @ts-ignore
|
|
20
|
+
if (error.code === "ENOENT" && args.repo) {
|
|
21
|
+
const projectId = await generateProjectId({ repo: args.repo, projectPath: args.projectPath });
|
|
22
|
+
if (projectId) {
|
|
23
|
+
await args.repo.nodeishFs.writeFile(args.projectPath + "/project_id", projectId);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
export async function generateProjectId(args) {
|
|
29
|
+
if (!args.repo || !args.projectPath) {
|
|
30
|
+
return undefined;
|
|
31
|
+
}
|
|
32
|
+
const firstCommitHash = await args.repo.getFirstCommitHash();
|
|
33
|
+
if (firstCommitHash) {
|
|
34
|
+
return hash(`${firstCommitHash + args.projectPath}`);
|
|
35
|
+
}
|
|
36
|
+
return undefined;
|
|
37
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"maybeCreateFirstProjectId.test.d.ts","sourceRoot":"","sources":["../../src/migrations/maybeCreateFirstProjectId.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { generateProjectId } from "./maybeCreateFirstProjectId.js";
|
|
2
|
+
import { it, expect } from "vitest";
|
|
3
|
+
import { openRepository } from "@lix-js/client/src/openRepository.ts";
|
|
4
|
+
import { mockRepo, createNodeishMemoryFs } from "@lix-js/client";
|
|
5
|
+
import {} from "@lix-js/fs";
|
|
6
|
+
// eslint-disable-next-line no-restricted-imports -- test
|
|
7
|
+
import { readFileSync } from "node:fs";
|
|
8
|
+
const ciTestRepo = JSON.parse(readFileSync("./mocks/ci-test-repo-no-shallow.json", { encoding: "utf-8" }));
|
|
9
|
+
const repo = await mockRepo({ fromSnapshot: ciTestRepo });
|
|
10
|
+
it("should return if repo is undefined", async () => {
|
|
11
|
+
const projectId = await generateProjectId({ repo: undefined, projectPath: "mocked_project_path" });
|
|
12
|
+
expect(projectId).toBeUndefined();
|
|
13
|
+
});
|
|
14
|
+
it("should generate a project id", async () => {
|
|
15
|
+
const projectId = await generateProjectId({ repo, projectPath: "mocked_project_path" });
|
|
16
|
+
expect(projectId).toBe("432d7ef29c510e99d95e2d14ef57a0797a1603859b5a851b7dff7e77161b8c08");
|
|
17
|
+
});
|
|
18
|
+
it("should return undefined if repoMeta contains error", async () => {
|
|
19
|
+
const repoWithError = await openRepository("https://github.com/inlang/no-exist", {
|
|
20
|
+
nodeishFs: createNodeishMemoryFs(),
|
|
21
|
+
});
|
|
22
|
+
const projectId = await generateProjectId({
|
|
23
|
+
repo: repoWithError,
|
|
24
|
+
projectPath: "mocked_project_path",
|
|
25
|
+
});
|
|
26
|
+
expect(projectId).toBeUndefined();
|
|
27
|
+
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { NodeishFilesystem } from "@lix-js/fs";
|
|
2
2
|
/**
|
|
3
3
|
* Migrates to the new project directory structure
|
|
4
|
-
* https://github.com/
|
|
4
|
+
* https://github.com/opral/monorepo/issues/1678
|
|
5
5
|
*/
|
|
6
6
|
export declare const maybeMigrateToDirectory: (args: {
|
|
7
7
|
nodeishFs: NodeishFilesystem;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { tryCatch } from "@inlang/result";
|
|
2
2
|
/**
|
|
3
3
|
* Migrates to the new project directory structure
|
|
4
|
-
* https://github.com/
|
|
4
|
+
* https://github.com/opral/monorepo/issues/1678
|
|
5
5
|
*/
|
|
6
6
|
export const maybeMigrateToDirectory = async (args) => {
|
|
7
7
|
// the migration assumes that the projectPath ends with project.inlang
|
|
@@ -38,9 +38,9 @@ The \`project.inlang.json\` file is now contained in a project directory e.g. \`
|
|
|
38
38
|
## Why is this happening?
|
|
39
39
|
|
|
40
40
|
See this RFC https://docs.google.com/document/d/1OYyA1wYfQRbIJOIBDliYoWjiUlkFBNxH_U2R4WpVRZ4/edit#heading=h.pecv6xb7ial6
|
|
41
|
-
and the following GitHub issue for more information https://github.com/
|
|
41
|
+
and the following GitHub issue for more information https://github.com/opral/monorepo/issues/1678.
|
|
42
42
|
|
|
43
|
-
- Monorepo support https://github.com/
|
|
43
|
+
- Monorepo support https://github.com/opral/monorepo/discussions/258.
|
|
44
44
|
- Required for many other future features like caching, first class offline support, and more.
|
|
45
45
|
- Stablize the inlang project format.
|
|
46
46
|
`;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* List of telemetry events for typesafety.
|
|
3
|
+
*
|
|
4
|
+
* - prefix with `SDK` to avoid collisions with other apps
|
|
5
|
+
* - use past tense to indicate that the event is completed
|
|
6
|
+
*/
|
|
7
|
+
declare const events: readonly ["SDK loaded project"];
|
|
8
|
+
/**
|
|
9
|
+
* Capture an event.
|
|
10
|
+
*
|
|
11
|
+
* - manually calling the PostHog API because the SDKs were not platform angostic (and generally bloated)
|
|
12
|
+
*/
|
|
13
|
+
export declare const capture: (event: (typeof events)[number], args: {
|
|
14
|
+
projectId: string;
|
|
15
|
+
/**
|
|
16
|
+
* Please use snake_case for property names.
|
|
17
|
+
*/
|
|
18
|
+
properties: Record<string, any>;
|
|
19
|
+
}) => Promise<void>;
|
|
20
|
+
export {};
|
|
21
|
+
//# sourceMappingURL=capture.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capture.d.ts","sourceRoot":"","sources":["../../src/telemetry/capture.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,QAAA,MAAM,MAAM,iCAAkC,CAAA;AAE9C;;;;GAIG;AACH,eAAO,MAAM,OAAO,UACZ,CAAC,aAAa,CAAC,CAAC,MAAM,CAAC,QACxB;IACL,SAAS,EAAE,MAAM,CAAA;IACjB;;OAEG;IACH,UAAU,EAAE,OAAO,MAAM,EAAE,GAAG,CAAC,CAAA;CAC/B,kBAyBD,CAAA"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { ENV_VARIABLES } from "../env-variables/index.js";
|
|
2
|
+
/**
|
|
3
|
+
* List of telemetry events for typesafety.
|
|
4
|
+
*
|
|
5
|
+
* - prefix with `SDK` to avoid collisions with other apps
|
|
6
|
+
* - use past tense to indicate that the event is completed
|
|
7
|
+
*/
|
|
8
|
+
const events = ["SDK loaded project"];
|
|
9
|
+
/**
|
|
10
|
+
* Capture an event.
|
|
11
|
+
*
|
|
12
|
+
* - manually calling the PostHog API because the SDKs were not platform angostic (and generally bloated)
|
|
13
|
+
*/
|
|
14
|
+
export const capture = async (event, args) => {
|
|
15
|
+
// do not send events if the token is not set
|
|
16
|
+
// (assuming this eases testing)
|
|
17
|
+
if (ENV_VARIABLES.PUBLIC_POSTHOG_TOKEN === undefined) {
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
try {
|
|
21
|
+
await fetch("https://eu.posthog.com/capture/", {
|
|
22
|
+
method: "POST",
|
|
23
|
+
body: JSON.stringify({
|
|
24
|
+
api_key: ENV_VARIABLES.PUBLIC_POSTHOG_TOKEN,
|
|
25
|
+
event,
|
|
26
|
+
// id is "unknown" because no user information is available
|
|
27
|
+
distinct_id: "unknown",
|
|
28
|
+
properties: {
|
|
29
|
+
$groups: { project: args.projectId },
|
|
30
|
+
...args.properties,
|
|
31
|
+
},
|
|
32
|
+
}),
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
catch (e) {
|
|
36
|
+
// TODO implement sentry logging
|
|
37
|
+
// do not console.log and avoid exposing internal errors to the user
|
|
38
|
+
}
|
|
39
|
+
};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@inlang/sdk",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.24.0",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"publishConfig": {
|
|
7
7
|
"access": "public"
|
|
@@ -26,16 +26,16 @@
|
|
|
26
26
|
"solid-js": "1.6.12",
|
|
27
27
|
"throttle-debounce": "^5.0.0",
|
|
28
28
|
"@inlang/json-types": "1.1.0",
|
|
29
|
-
"@inlang/language-tag": "1.
|
|
30
|
-
"@inlang/message
|
|
31
|
-
"@inlang/message": "
|
|
32
|
-
"@inlang/module": "1.2.
|
|
33
|
-
"@inlang/plugin": "2.4.
|
|
34
|
-
"@inlang/project-settings": "2.2.0",
|
|
29
|
+
"@inlang/language-tag": "1.4.0",
|
|
30
|
+
"@inlang/message": "2.0.1",
|
|
31
|
+
"@inlang/message-lint-rule": "1.4.1",
|
|
32
|
+
"@inlang/module": "1.2.3",
|
|
33
|
+
"@inlang/plugin": "2.4.3",
|
|
35
34
|
"@inlang/result": "1.1.0",
|
|
36
|
-
"@inlang/translatable": "1.2.
|
|
37
|
-
"@
|
|
38
|
-
"@lix-js/fs": "0.
|
|
35
|
+
"@inlang/translatable": "1.2.1",
|
|
36
|
+
"@inlang/project-settings": "2.2.1",
|
|
37
|
+
"@lix-js/fs": "0.6.0",
|
|
38
|
+
"@lix-js/client": "0.6.0"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
41
|
"@types/throttle-debounce": "5.0.0",
|
|
@@ -47,8 +47,9 @@
|
|
|
47
47
|
"vitest": "^0.33.0"
|
|
48
48
|
},
|
|
49
49
|
"scripts": {
|
|
50
|
-
"build": "tsc --build",
|
|
51
|
-
"dev": "tsc --watch",
|
|
50
|
+
"build": "npm run prepare-env-variables && tsc --build",
|
|
51
|
+
"dev": "npm run prepare-env-variables && tsc --watch",
|
|
52
|
+
"prepare-env-variables": "node ./src/env-variables/createIndexFile.js",
|
|
52
53
|
"test": "tsc --noEmit && vitest run --passWithNoTests --coverage",
|
|
53
54
|
"lint": "eslint ./src --fix",
|
|
54
55
|
"format": "prettier ./src --write",
|