@inlang/sdk 0.24.1 → 0.26.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapter/solidAdapter.d.ts +1 -0
- package/dist/adapter/solidAdapter.d.ts.map +1 -1
- package/dist/adapter/solidAdapter.js +1 -0
- package/dist/adapter/solidAdapter.test.js +13 -14
- package/dist/api.d.ts +4 -0
- package/dist/api.d.ts.map +1 -1
- package/dist/loadProject.d.ts +1 -24
- package/dist/loadProject.d.ts.map +1 -1
- package/dist/loadProject.js +19 -11
- package/dist/loadProject.test.js +58 -65
- package/dist/telemetry/groupIdentify.d.ts +13 -0
- package/dist/telemetry/groupIdentify.d.ts.map +1 -0
- package/dist/telemetry/groupIdentify.js +35 -0
- package/package.json +5 -5
- package/src/adapter/solidAdapter.test.ts +13 -14
- package/src/adapter/solidAdapter.ts +2 -0
- package/src/api.ts +5 -0
- package/src/loadProject.test.ts +59 -66
- package/src/loadProject.ts +12 -42
- package/src/telemetry/groupIdentify.ts +41 -0
package/src/loadProject.test.ts
CHANGED
|
@@ -16,10 +16,10 @@ import {
|
|
|
16
16
|
ProjectSettingsFileNotFoundError,
|
|
17
17
|
ProjectSettingsInvalidError,
|
|
18
18
|
} from "./errors.js"
|
|
19
|
-
import {
|
|
19
|
+
import { normalizePath } from "@lix-js/fs"
|
|
20
20
|
import { createMessage } from "./test-utilities/createMessage.js"
|
|
21
21
|
import { tryCatch } from "@inlang/result"
|
|
22
|
-
import { mockRepo
|
|
22
|
+
import { mockRepo } from "@lix-js/client"
|
|
23
23
|
import { type Snapshot } from "@lix-js/fs"
|
|
24
24
|
// eslint-disable-next-line no-restricted-imports -- test
|
|
25
25
|
import { readFileSync } from "node:fs"
|
|
@@ -109,15 +109,11 @@ const _import: ImportFunction = async (name) =>
|
|
|
109
109
|
default: name === "plugin.js" ? mockPlugin : mockMessageLintRule,
|
|
110
110
|
} satisfies InlangModule)
|
|
111
111
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
readFileSync(resolve(__dirname, "../mocks/ci-test-repo-no-shallow.json"), {
|
|
116
|
-
encoding: "utf-8",
|
|
117
|
-
})
|
|
118
|
-
) as Snapshot,
|
|
112
|
+
const ciTestRepoSnapshot = JSON.parse(
|
|
113
|
+
readFileSync(resolve(__dirname, "../mocks/ci-test-repo-no-shallow.json"), {
|
|
114
|
+
encoding: "utf-8",
|
|
119
115
|
})
|
|
120
|
-
|
|
116
|
+
) as Snapshot
|
|
121
117
|
|
|
122
118
|
// ------------------------------------------------------------------------------------------------
|
|
123
119
|
|
|
@@ -128,8 +124,7 @@ async function openCiTestRepo() {
|
|
|
128
124
|
* like files: they can be renamed and moved around.
|
|
129
125
|
*/
|
|
130
126
|
it("should throw if a project (path) does not have a name", async () => {
|
|
131
|
-
const
|
|
132
|
-
const repo = await openRepository("file://", { nodeishFs: fs })
|
|
127
|
+
const repo = await mockRepo()
|
|
133
128
|
const project = await tryCatch(() =>
|
|
134
129
|
loadProject({
|
|
135
130
|
projectPath: "/source-code/.inlang",
|
|
@@ -141,8 +136,7 @@ it("should throw if a project (path) does not have a name", async () => {
|
|
|
141
136
|
})
|
|
142
137
|
|
|
143
138
|
it("should throw if a project path does not end with .inlang", async () => {
|
|
144
|
-
const
|
|
145
|
-
const repo = await openRepository("file://", { nodeishFs: fs })
|
|
139
|
+
const repo = await mockRepo()
|
|
146
140
|
|
|
147
141
|
const invalidPaths = [
|
|
148
142
|
"/source-code/frontend.inlang/settings",
|
|
@@ -164,8 +158,7 @@ it("should throw if a project path does not end with .inlang", async () => {
|
|
|
164
158
|
|
|
165
159
|
describe("initialization", () => {
|
|
166
160
|
it("should throw if projectPath is not an absolute path", async () => {
|
|
167
|
-
const
|
|
168
|
-
const repo = await openRepository("file://", { nodeishFs: fs })
|
|
161
|
+
const repo = await mockRepo()
|
|
169
162
|
|
|
170
163
|
const result = await tryCatch(() =>
|
|
171
164
|
loadProject({
|
|
@@ -179,7 +172,7 @@ describe("initialization", () => {
|
|
|
179
172
|
})
|
|
180
173
|
|
|
181
174
|
it("should generate projectId on missing projectid", async () => {
|
|
182
|
-
const repo = await
|
|
175
|
+
const repo = await mockRepo({ fromSnapshot: ciTestRepoSnapshot })
|
|
183
176
|
|
|
184
177
|
const existing = await repo.nodeishFs
|
|
185
178
|
.readFile("/project.inlang/project_id", {
|
|
@@ -215,7 +208,7 @@ describe("initialization", () => {
|
|
|
215
208
|
})
|
|
216
209
|
|
|
217
210
|
it("should reuse projectId on existing projectid", async () => {
|
|
218
|
-
const repo = await
|
|
211
|
+
const repo = await mockRepo({ fromSnapshot: ciTestRepoSnapshot })
|
|
219
212
|
|
|
220
213
|
repo.nodeishFs.writeFile("/project.inlang/project_id", "testId")
|
|
221
214
|
|
|
@@ -242,10 +235,10 @@ describe("initialization", () => {
|
|
|
242
235
|
})
|
|
243
236
|
|
|
244
237
|
it("should resolve from a windows path", async () => {
|
|
245
|
-
const
|
|
238
|
+
const repo = await mockRepo()
|
|
239
|
+
const fs = repo.nodeishFs
|
|
246
240
|
fs.mkdir("C:\\Users\\user\\project.inlang", { recursive: true })
|
|
247
241
|
fs.writeFile("C:\\Users\\user\\project.inlang\\settings.json", JSON.stringify(settings))
|
|
248
|
-
const repo = await openRepository("file://", { nodeishFs: fs })
|
|
249
242
|
|
|
250
243
|
const result = await tryCatch(() =>
|
|
251
244
|
loadProject({
|
|
@@ -261,9 +254,9 @@ describe("initialization", () => {
|
|
|
261
254
|
|
|
262
255
|
describe("settings", () => {
|
|
263
256
|
it("should return an error if settings file is not found", async () => {
|
|
264
|
-
const
|
|
257
|
+
const repo = await mockRepo()
|
|
258
|
+
const fs = repo.nodeishFs
|
|
265
259
|
fs.mkdir("/user/project", { recursive: true })
|
|
266
|
-
const repo = await openRepository("file://", { nodeishFs: fs })
|
|
267
260
|
|
|
268
261
|
const project = await loadProject({
|
|
269
262
|
projectPath: "/user/non-existend-project.inlang",
|
|
@@ -275,10 +268,10 @@ describe("initialization", () => {
|
|
|
275
268
|
})
|
|
276
269
|
|
|
277
270
|
it("should return an error if settings file is not a valid JSON", async () => {
|
|
278
|
-
const
|
|
271
|
+
const repo = await mockRepo()
|
|
272
|
+
const fs = repo.nodeishFs
|
|
279
273
|
await fs.mkdir("/user/project.inlang", { recursive: true })
|
|
280
274
|
await fs.writeFile("/user/project.inlang/settings.json", "invalid json")
|
|
281
|
-
const repo = await openRepository("file://", { nodeishFs: fs })
|
|
282
275
|
|
|
283
276
|
const project = await loadProject({
|
|
284
277
|
projectPath: "/user/project.inlang",
|
|
@@ -290,10 +283,10 @@ describe("initialization", () => {
|
|
|
290
283
|
})
|
|
291
284
|
|
|
292
285
|
it("should return an error if settings file is does not match schema", async () => {
|
|
293
|
-
const
|
|
286
|
+
const repo = await mockRepo()
|
|
287
|
+
const fs = repo.nodeishFs
|
|
294
288
|
await fs.mkdir("/user/project.inlang", { recursive: true })
|
|
295
289
|
await fs.writeFile("/user/project.inlang/settings.json", JSON.stringify({}))
|
|
296
|
-
const repo = await openRepository("file://", { nodeishFs: fs })
|
|
297
290
|
|
|
298
291
|
const project = await loadProject({
|
|
299
292
|
projectPath: "/user/project.inlang",
|
|
@@ -305,10 +298,10 @@ describe("initialization", () => {
|
|
|
305
298
|
})
|
|
306
299
|
|
|
307
300
|
it("should return the parsed settings", async () => {
|
|
308
|
-
const
|
|
301
|
+
const repo = await mockRepo()
|
|
302
|
+
const fs = repo.nodeishFs
|
|
309
303
|
await fs.mkdir("/user/project.inlang", { recursive: true })
|
|
310
304
|
await fs.writeFile("/user/project.inlang/settings.json", JSON.stringify(settings))
|
|
311
|
-
const repo = await openRepository("file://", { nodeishFs: fs })
|
|
312
305
|
const project = await loadProject({
|
|
313
306
|
projectPath: "/user/project.inlang",
|
|
314
307
|
repo,
|
|
@@ -319,11 +312,11 @@ describe("initialization", () => {
|
|
|
319
312
|
})
|
|
320
313
|
|
|
321
314
|
it("should not re-write the settings to disk when initializing", async () => {
|
|
322
|
-
const
|
|
315
|
+
const repo = await mockRepo()
|
|
316
|
+
const fs = repo.nodeishFs
|
|
323
317
|
const settingsWithDeifferentFormatting = JSON.stringify(settings, undefined, 4)
|
|
324
318
|
await fs.mkdir("/user/project.inlang", { recursive: true })
|
|
325
319
|
await fs.writeFile("/user/project.inlang/settings.json", settingsWithDeifferentFormatting)
|
|
326
|
-
const repo = await openRepository("file://", { nodeishFs: fs })
|
|
327
320
|
|
|
328
321
|
const project = await loadProject({
|
|
329
322
|
projectPath: "/user/project.inlang",
|
|
@@ -354,10 +347,10 @@ describe("initialization", () => {
|
|
|
354
347
|
default: {} as Plugin,
|
|
355
348
|
} satisfies InlangModule)
|
|
356
349
|
|
|
357
|
-
const
|
|
350
|
+
const repo = await mockRepo()
|
|
351
|
+
const fs = repo.nodeishFs
|
|
358
352
|
await fs.mkdir("/user/project.inlang", { recursive: true })
|
|
359
353
|
await fs.writeFile("/user/project.inlang/settings.json", JSON.stringify(settings))
|
|
360
|
-
const repo = await openRepository("file://", { nodeishFs: fs })
|
|
361
354
|
|
|
362
355
|
const project = await loadProject({
|
|
363
356
|
projectPath: "/user/project.inlang",
|
|
@@ -388,10 +381,10 @@ describe("initialization", () => {
|
|
|
388
381
|
describe("functionality", () => {
|
|
389
382
|
describe("settings", () => {
|
|
390
383
|
it("should return the settings", async () => {
|
|
391
|
-
const
|
|
384
|
+
const repo = await mockRepo()
|
|
385
|
+
const fs = repo.nodeishFs
|
|
392
386
|
await fs.mkdir("/user/project.inlang", { recursive: true })
|
|
393
387
|
await fs.writeFile("/user/project.inlang/settings.json", JSON.stringify(settings))
|
|
394
|
-
const repo = await openRepository("file://", { nodeishFs: fs })
|
|
395
388
|
const project = await loadProject({
|
|
396
389
|
projectPath: "/user/project.inlang",
|
|
397
390
|
repo,
|
|
@@ -402,10 +395,10 @@ describe("functionality", () => {
|
|
|
402
395
|
})
|
|
403
396
|
|
|
404
397
|
it("should set a new settings", async () => {
|
|
405
|
-
const
|
|
398
|
+
const repo = await mockRepo()
|
|
399
|
+
const fs = repo.nodeishFs
|
|
406
400
|
await fs.mkdir("/user/project.inlang", { recursive: true })
|
|
407
401
|
await fs.writeFile("/user/project.inlang/settings.json", JSON.stringify(settings))
|
|
408
|
-
const repo = await openRepository("file://", { nodeishFs: fs })
|
|
409
402
|
const project = await loadProject({
|
|
410
403
|
projectPath: "/user/project.inlang",
|
|
411
404
|
repo,
|
|
@@ -429,10 +422,10 @@ describe("functionality", () => {
|
|
|
429
422
|
|
|
430
423
|
describe("setSettings", () => {
|
|
431
424
|
it("should fail if settings are not valid", async () => {
|
|
432
|
-
const
|
|
425
|
+
const repo = await mockRepo()
|
|
426
|
+
const fs = repo.nodeishFs
|
|
433
427
|
await fs.mkdir("/user/project.inlang", { recursive: true })
|
|
434
428
|
await fs.writeFile("/user/project.inlang/settings.json", JSON.stringify(settings))
|
|
435
|
-
const repo = await openRepository("file://", { nodeishFs: fs })
|
|
436
429
|
const project = await loadProject({
|
|
437
430
|
projectPath: "/user/project.inlang",
|
|
438
431
|
repo,
|
|
@@ -445,7 +438,8 @@ describe("functionality", () => {
|
|
|
445
438
|
})
|
|
446
439
|
|
|
447
440
|
it("should throw an error if sourceLanguageTag is not in languageTags", async () => {
|
|
448
|
-
const
|
|
441
|
+
const repo = await mockRepo()
|
|
442
|
+
const fs = repo.nodeishFs
|
|
449
443
|
await fs.mkdir("/user/project.inlang", { recursive: true })
|
|
450
444
|
|
|
451
445
|
const settings: ProjectSettings = {
|
|
@@ -455,7 +449,6 @@ describe("functionality", () => {
|
|
|
455
449
|
}
|
|
456
450
|
|
|
457
451
|
await fs.writeFile("/user/project.inlang/settings.json", JSON.stringify(settings))
|
|
458
|
-
const repo = await openRepository("file://", { nodeishFs: fs })
|
|
459
452
|
|
|
460
453
|
const project = await loadProject({
|
|
461
454
|
projectPath: "/user/project.inlang",
|
|
@@ -468,10 +461,10 @@ describe("functionality", () => {
|
|
|
468
461
|
})
|
|
469
462
|
|
|
470
463
|
it("should write settings to disk", async () => {
|
|
471
|
-
const
|
|
464
|
+
const repo = await mockRepo()
|
|
465
|
+
const fs = repo.nodeishFs
|
|
472
466
|
await fs.mkdir("/user/project.inlang", { recursive: true })
|
|
473
467
|
await fs.writeFile("/user/project.inlang/settings.json", JSON.stringify(settings))
|
|
474
|
-
const repo = await openRepository("file://", { nodeishFs: fs })
|
|
475
468
|
const project = await loadProject({
|
|
476
469
|
projectPath: "/user/project.inlang",
|
|
477
470
|
repo,
|
|
@@ -496,7 +489,8 @@ describe("functionality", () => {
|
|
|
496
489
|
|
|
497
490
|
describe("installed", () => {
|
|
498
491
|
it("should return the installed items", async () => {
|
|
499
|
-
const
|
|
492
|
+
const repo = await mockRepo()
|
|
493
|
+
const fs = repo.nodeishFs
|
|
500
494
|
const settings: ProjectSettings = {
|
|
501
495
|
sourceLanguageTag: "en",
|
|
502
496
|
languageTags: ["en"],
|
|
@@ -504,7 +498,6 @@ describe("functionality", () => {
|
|
|
504
498
|
}
|
|
505
499
|
await fs.mkdir("/user/project.inlang", { recursive: true })
|
|
506
500
|
await fs.writeFile("/user/project.inlang/settings.json", JSON.stringify(settings))
|
|
507
|
-
const repo = await openRepository("file://", { nodeishFs: fs })
|
|
508
501
|
const project = await loadProject({
|
|
509
502
|
projectPath: "/user/project.inlang",
|
|
510
503
|
repo,
|
|
@@ -528,7 +521,8 @@ describe("functionality", () => {
|
|
|
528
521
|
})
|
|
529
522
|
|
|
530
523
|
it("should apply 'warning' as default lint level to lint rules that have no lint level defined in the settings", async () => {
|
|
531
|
-
const
|
|
524
|
+
const repo = await mockRepo()
|
|
525
|
+
const fs = repo.nodeishFs
|
|
532
526
|
|
|
533
527
|
const settings: ProjectSettings = {
|
|
534
528
|
sourceLanguageTag: "en",
|
|
@@ -538,7 +532,6 @@ describe("functionality", () => {
|
|
|
538
532
|
|
|
539
533
|
await fs.mkdir("/user/project.inlang", { recursive: true })
|
|
540
534
|
await fs.writeFile("/user/project.inlang/settings.json", JSON.stringify(settings))
|
|
541
|
-
const repo = await openRepository("file://", { nodeishFs: fs })
|
|
542
535
|
|
|
543
536
|
const project = await loadProject({
|
|
544
537
|
projectPath: "/user/project.inlang",
|
|
@@ -571,7 +564,8 @@ describe("functionality", () => {
|
|
|
571
564
|
loadMessages: () => [{ id: "some-message", selectors: [], variants: [] }],
|
|
572
565
|
saveMessages: () => undefined,
|
|
573
566
|
}
|
|
574
|
-
const
|
|
567
|
+
const repo = await mockRepo()
|
|
568
|
+
const fs = repo.nodeishFs
|
|
575
569
|
await fs.mkdir("/user/project.inlang", { recursive: true })
|
|
576
570
|
await fs.writeFile(
|
|
577
571
|
"/user/project.inlang/settings.json",
|
|
@@ -581,7 +575,6 @@ describe("functionality", () => {
|
|
|
581
575
|
modules: ["plugin.js", "lintRule.js"],
|
|
582
576
|
} satisfies ProjectSettings)
|
|
583
577
|
)
|
|
584
|
-
const repo = await openRepository("file://", { nodeishFs: fs })
|
|
585
578
|
|
|
586
579
|
const _import: ImportFunction = async (name) => {
|
|
587
580
|
return {
|
|
@@ -623,7 +616,8 @@ describe("functionality", () => {
|
|
|
623
616
|
loadMessages: () => [{ id: "some-message", selectors: [], variants: [] }],
|
|
624
617
|
saveMessages: () => undefined,
|
|
625
618
|
}
|
|
626
|
-
const
|
|
619
|
+
const repo = await mockRepo()
|
|
620
|
+
const fs = repo.nodeishFs
|
|
627
621
|
await fs.mkdir("/user/project.inlang", { recursive: true })
|
|
628
622
|
await fs.writeFile(
|
|
629
623
|
"/user/project.inlang/settings.json",
|
|
@@ -633,7 +627,6 @@ describe("functionality", () => {
|
|
|
633
627
|
modules: ["plugin.js", "lintRule.js"],
|
|
634
628
|
} satisfies ProjectSettings)
|
|
635
629
|
)
|
|
636
|
-
const repo = await openRepository("file://", { nodeishFs: fs })
|
|
637
630
|
const _import: ImportFunction = async (name) => {
|
|
638
631
|
return {
|
|
639
632
|
default: name === "plugin.js" ? _mockPlugin : _mockLintRule,
|
|
@@ -656,10 +649,10 @@ describe("functionality", () => {
|
|
|
656
649
|
|
|
657
650
|
describe("errors", () => {
|
|
658
651
|
it("should return the errors", async () => {
|
|
659
|
-
const
|
|
652
|
+
const repo = await mockRepo()
|
|
653
|
+
const fs = repo.nodeishFs
|
|
660
654
|
await fs.mkdir("/user/project.inlang", { recursive: true })
|
|
661
655
|
await fs.writeFile("/user/project.inlang/settings.json", JSON.stringify(settings))
|
|
662
|
-
const repo = await openRepository("file://", { nodeishFs: fs })
|
|
663
656
|
const project = await loadProject({
|
|
664
657
|
projectPath: "/user/project.inlang",
|
|
665
658
|
repo,
|
|
@@ -673,10 +666,10 @@ describe("functionality", () => {
|
|
|
673
666
|
|
|
674
667
|
describe("customApi", () => {
|
|
675
668
|
it("should return the app specific api", async () => {
|
|
676
|
-
const
|
|
669
|
+
const repo = await mockRepo()
|
|
670
|
+
const fs = repo.nodeishFs
|
|
677
671
|
await fs.mkdir("/user/project.inlang", { recursive: true })
|
|
678
672
|
await fs.writeFile("/user/project.inlang/settings.json", JSON.stringify(settings))
|
|
679
|
-
const repo = await openRepository("file://", { nodeishFs: fs })
|
|
680
673
|
const project = await loadProject({
|
|
681
674
|
projectPath: "/user/project.inlang",
|
|
682
675
|
repo,
|
|
@@ -691,10 +684,10 @@ describe("functionality", () => {
|
|
|
691
684
|
|
|
692
685
|
describe("messages", () => {
|
|
693
686
|
it("should return the messages", async () => {
|
|
694
|
-
const
|
|
687
|
+
const repo = await mockRepo()
|
|
688
|
+
const fs = repo.nodeishFs
|
|
695
689
|
await fs.mkdir("/user/project.inlang", { recursive: true })
|
|
696
690
|
await fs.writeFile("/user/project.inlang/settings.json", JSON.stringify(settings))
|
|
697
|
-
const repo = await openRepository("file://", { nodeishFs: fs })
|
|
698
691
|
const project = await loadProject({
|
|
699
692
|
projectPath: "/user/project.inlang",
|
|
700
693
|
repo,
|
|
@@ -707,7 +700,8 @@ describe("functionality", () => {
|
|
|
707
700
|
|
|
708
701
|
describe("query", () => {
|
|
709
702
|
it("should call saveMessages() on updates", async () => {
|
|
710
|
-
const
|
|
703
|
+
const repo = await mockRepo()
|
|
704
|
+
const fs = repo.nodeishFs
|
|
711
705
|
|
|
712
706
|
const settings: ProjectSettings = {
|
|
713
707
|
sourceLanguageTag: "en",
|
|
@@ -722,7 +716,6 @@ describe("functionality", () => {
|
|
|
722
716
|
await fs.writeFile("/user/project.inlang/settings.json", JSON.stringify(settings))
|
|
723
717
|
|
|
724
718
|
await fs.mkdir("./resources")
|
|
725
|
-
const repo = await openRepository("file://", { nodeishFs: fs })
|
|
726
719
|
|
|
727
720
|
const mockSaveFn = vi.fn()
|
|
728
721
|
|
|
@@ -885,7 +878,8 @@ describe("functionality", () => {
|
|
|
885
878
|
* - Might be slow for a large number of messages. The requirement hasn't popped up yet though.
|
|
886
879
|
*/
|
|
887
880
|
it("should pass all messages, regardless of which message changed, to saveMessages()", async () => {
|
|
888
|
-
const
|
|
881
|
+
const repo = await mockRepo()
|
|
882
|
+
const fs = repo.nodeishFs
|
|
889
883
|
|
|
890
884
|
const settings: ProjectSettings = {
|
|
891
885
|
sourceLanguageTag: "en",
|
|
@@ -898,7 +892,6 @@ describe("functionality", () => {
|
|
|
898
892
|
|
|
899
893
|
await fs.mkdir("./project.inlang", { recursive: true })
|
|
900
894
|
await fs.writeFile("./project.inlang/settings.json", JSON.stringify(settings))
|
|
901
|
-
const repo = await openRepository("file://", { nodeishFs: fs })
|
|
902
895
|
|
|
903
896
|
const mockSaveFn = vi.fn()
|
|
904
897
|
|
|
@@ -938,10 +931,10 @@ describe("functionality", () => {
|
|
|
938
931
|
|
|
939
932
|
describe("lint", () => {
|
|
940
933
|
it.todo("should throw if lint reports are not initialized yet", async () => {
|
|
941
|
-
const
|
|
934
|
+
const repo = await mockRepo()
|
|
935
|
+
const fs = repo.nodeishFs
|
|
942
936
|
await fs.mkdir("/user/project", { recursive: true })
|
|
943
937
|
await fs.writeFile("/user/project/project.inlang.json", JSON.stringify(settings))
|
|
944
|
-
const repo = await openRepository("file://", { nodeishFs: fs })
|
|
945
938
|
const project = await loadProject({
|
|
946
939
|
projectPath: "/user/project/project.inlang.json",
|
|
947
940
|
repo,
|
|
@@ -961,10 +954,10 @@ describe("functionality", () => {
|
|
|
961
954
|
languageTags: ["en"],
|
|
962
955
|
modules: ["lintRule.js"],
|
|
963
956
|
}
|
|
964
|
-
const
|
|
957
|
+
const repo = await mockRepo()
|
|
958
|
+
const fs = repo.nodeishFs
|
|
965
959
|
await fs.mkdir("/user/project.inlang", { recursive: true })
|
|
966
960
|
await fs.writeFile("/user/project.inlang/settings.json", JSON.stringify(settings))
|
|
967
|
-
const repo = await openRepository("file://", { nodeishFs: fs })
|
|
968
961
|
const project = await loadProject({
|
|
969
962
|
projectPath: "/user/project.inlang",
|
|
970
963
|
repo,
|
|
@@ -979,7 +972,8 @@ describe("functionality", () => {
|
|
|
979
972
|
|
|
980
973
|
describe("watcher", () => {
|
|
981
974
|
it("changing files in resources should trigger callback of message query", async () => {
|
|
982
|
-
const
|
|
975
|
+
const repo = await mockRepo()
|
|
976
|
+
const fs = repo.nodeishFs
|
|
983
977
|
|
|
984
978
|
const messages = {
|
|
985
979
|
$schema: "https://inlang.com/schema/inlang-message-format",
|
|
@@ -1030,7 +1024,6 @@ describe("functionality", () => {
|
|
|
1030
1024
|
|
|
1031
1025
|
await fs.mkdir("./project.inlang", { recursive: true })
|
|
1032
1026
|
await fs.writeFile("./project.inlang/settings.json", JSON.stringify(settings))
|
|
1033
|
-
const repo = await openRepository("file://", { nodeishFs: fs })
|
|
1034
1027
|
|
|
1035
1028
|
// establish watcher
|
|
1036
1029
|
const project = await loadProject({
|
package/src/loadProject.ts
CHANGED
|
@@ -30,39 +30,16 @@ import { maybeMigrateToDirectory } from "./migrations/migrateToDirectory.js"
|
|
|
30
30
|
import { maybeCreateFirstProjectId } from "./migrations/maybeCreateFirstProjectId.js"
|
|
31
31
|
import type { Repository } from "@lix-js/client"
|
|
32
32
|
import { capture } from "./telemetry/capture.js"
|
|
33
|
+
import { identifyProject } from "./telemetry/groupIdentify.js"
|
|
33
34
|
|
|
34
35
|
const settingsCompiler = TypeCompiler.Compile(ProjectSettings)
|
|
35
36
|
|
|
36
|
-
/**
|
|
37
|
-
* Creates an inlang instance.
|
|
38
|
-
*
|
|
39
|
-
* @param projectPath - Absolute path to the inlang settings file.
|
|
40
|
-
* @param @deprecated nodeishFs - Filesystem that implements the NodeishFilesystemSubset interface.
|
|
41
|
-
* @param _import - Use `_import` to pass a custom import function for testing,
|
|
42
|
-
* and supporting legacy resolvedModules such as CJS.
|
|
43
|
-
*
|
|
44
|
-
*/
|
|
45
|
-
export async function loadProject(args: {
|
|
46
|
-
projectPath: string
|
|
47
|
-
nodeishFs: Repository["nodeishFs"]
|
|
48
|
-
/**
|
|
49
|
-
* The app id is used to identify the app that is using the SDK.
|
|
50
|
-
*
|
|
51
|
-
* We use the app id to group events in telemetry to answer questions
|
|
52
|
-
* like "Which apps causes these errors?" or "Which apps are used more than others?".
|
|
53
|
-
*
|
|
54
|
-
* @example
|
|
55
|
-
* appId: "app.inlang.badge"
|
|
56
|
-
*/
|
|
57
|
-
appId?: string
|
|
58
|
-
_import?: ImportFunction
|
|
59
|
-
}): Promise<InlangProject>
|
|
60
|
-
|
|
61
37
|
/**
|
|
62
38
|
* @param projectPath - Absolute path to the inlang settings file.
|
|
63
39
|
* @param repo - An instance of a lix repo as returned by `openRepository`.
|
|
64
40
|
* @param _import - Use `_import` to pass a custom import function for testing,
|
|
65
41
|
* and supporting legacy resolvedModules such as CJS.
|
|
42
|
+
* @param appId - The app id to use for telemetry e.g "app.inlang.badge"
|
|
66
43
|
*
|
|
67
44
|
*/
|
|
68
45
|
export async function loadProject(args: {
|
|
@@ -70,14 +47,6 @@ export async function loadProject(args: {
|
|
|
70
47
|
repo: Repository
|
|
71
48
|
appId?: string
|
|
72
49
|
_import?: ImportFunction
|
|
73
|
-
}): Promise<InlangProject>
|
|
74
|
-
|
|
75
|
-
export async function loadProject(args: {
|
|
76
|
-
projectPath: string
|
|
77
|
-
repo?: Repository
|
|
78
|
-
appId?: string
|
|
79
|
-
_import?: ImportFunction
|
|
80
|
-
nodeishFs?: Repository["nodeishFs"]
|
|
81
50
|
}): Promise<InlangProject> {
|
|
82
51
|
const projectPath = normalizePath(args.projectPath)
|
|
83
52
|
|
|
@@ -98,15 +67,7 @@ export async function loadProject(args: {
|
|
|
98
67
|
)
|
|
99
68
|
}
|
|
100
69
|
|
|
101
|
-
|
|
102
|
-
if (args.nodeishFs) {
|
|
103
|
-
// TODO: deprecate
|
|
104
|
-
fs = args.nodeishFs
|
|
105
|
-
} else if (args.repo) {
|
|
106
|
-
fs = args.repo.nodeishFs
|
|
107
|
-
} else {
|
|
108
|
-
throw new LoadProjectInvalidArgument(`Repo missing from arguments.`, { argument: "repo" })
|
|
109
|
-
}
|
|
70
|
+
const fs = args.repo.nodeishFs
|
|
110
71
|
|
|
111
72
|
const nodeishFs = createNodeishFsWithAbsolutePaths({
|
|
112
73
|
projectPath,
|
|
@@ -319,6 +280,14 @@ export async function loadProject(args: {
|
|
|
319
280
|
if (projectId && projectLoadedCapturedAlready === false) {
|
|
320
281
|
projectLoadedCapturedAlready = true
|
|
321
282
|
// TODO ensure that capture is "awaited" without blocking the the app from starting
|
|
283
|
+
await identifyProject({
|
|
284
|
+
projectId,
|
|
285
|
+
properties: {
|
|
286
|
+
// using the id for now as a name but can be changed in the future
|
|
287
|
+
// we need at least one property to make a project visible in the dashboard
|
|
288
|
+
name: projectId,
|
|
289
|
+
},
|
|
290
|
+
})
|
|
322
291
|
await capture("SDK loaded project", {
|
|
323
292
|
projectId,
|
|
324
293
|
properties: {
|
|
@@ -332,6 +301,7 @@ export async function loadProject(args: {
|
|
|
332
301
|
}
|
|
333
302
|
|
|
334
303
|
return {
|
|
304
|
+
id: projectId,
|
|
335
305
|
installed: {
|
|
336
306
|
plugins: createSubscribable(() => installedPlugins()),
|
|
337
307
|
messageLintRules: createSubscribable(() => installedMessageLintRules()),
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { ENV_VARIABLES } from "../env-variables/index.js"
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Capture an event.
|
|
5
|
+
*
|
|
6
|
+
* - manually calling the PostHog API because the SDKs were not platform angostic (and generally bloated)
|
|
7
|
+
*/
|
|
8
|
+
export const identifyProject = async (args: {
|
|
9
|
+
projectId: string
|
|
10
|
+
/**
|
|
11
|
+
* Please use snake_case for property names.
|
|
12
|
+
*/
|
|
13
|
+
properties: Record<string, any>
|
|
14
|
+
}) => {
|
|
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: "$groupidentify",
|
|
26
|
+
// id is "unknown" because no user information is available
|
|
27
|
+
distinct_id: "unknown",
|
|
28
|
+
properties: {
|
|
29
|
+
$group_type: "project",
|
|
30
|
+
$group_key: args.projectId,
|
|
31
|
+
$group_set: {
|
|
32
|
+
...args.properties,
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
}),
|
|
36
|
+
})
|
|
37
|
+
} catch (e) {
|
|
38
|
+
// TODO implement sentry logging
|
|
39
|
+
// do not console.log and avoid exposing internal errors to the user
|
|
40
|
+
}
|
|
41
|
+
}
|