@inlang/sdk 0.17.0 → 0.19.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.
Files changed (42) hide show
  1. package/dist/adapter/solidAdapter.test.js +16 -15
  2. package/dist/createNodeishFsWithAbsolutePaths.d.ts +2 -2
  3. package/dist/createNodeishFsWithAbsolutePaths.d.ts.map +1 -1
  4. package/dist/createNodeishFsWithAbsolutePaths.js +5 -4
  5. package/dist/createNodeishFsWithAbsolutePaths.test.js +5 -4
  6. package/dist/createNodeishFsWithWatcher.d.ts +12 -0
  7. package/dist/createNodeishFsWithWatcher.d.ts.map +1 -0
  8. package/dist/createNodeishFsWithWatcher.js +52 -0
  9. package/dist/createNodeishFsWithWatcher.test.d.ts +2 -0
  10. package/dist/createNodeishFsWithWatcher.test.d.ts.map +1 -0
  11. package/dist/createNodeishFsWithWatcher.test.js +32 -0
  12. package/dist/isAbsolutePath.test.js +1 -1
  13. package/dist/loadProject.d.ts +4 -4
  14. package/dist/loadProject.d.ts.map +1 -1
  15. package/dist/loadProject.js +45 -24
  16. package/dist/loadProject.test.js +175 -74
  17. package/dist/migrations/migrateToDirectory.d.ts +10 -0
  18. package/dist/migrations/migrateToDirectory.d.ts.map +1 -0
  19. package/dist/migrations/migrateToDirectory.js +46 -0
  20. package/dist/migrations/migrateToDirectory.test.d.ts +2 -0
  21. package/dist/migrations/migrateToDirectory.test.d.ts.map +1 -0
  22. package/dist/migrations/migrateToDirectory.test.js +48 -0
  23. package/dist/resolve-modules/plugins/resolvePlugins.js +1 -1
  24. package/dist/resolve-modules/plugins/resolvePlugins.test.js +2 -1
  25. package/dist/resolve-modules/plugins/types.d.ts +2 -1
  26. package/dist/resolve-modules/plugins/types.d.ts.map +1 -1
  27. package/dist/resolve-modules/validateModuleSettings.test.js +1 -1
  28. package/package.json +56 -56
  29. package/src/adapter/solidAdapter.test.ts +16 -15
  30. package/src/createNodeishFsWithAbsolutePaths.test.ts +5 -4
  31. package/src/createNodeishFsWithAbsolutePaths.ts +9 -5
  32. package/src/createNodeishFsWithWatcher.test.ts +40 -0
  33. package/src/createNodeishFsWithWatcher.ts +58 -0
  34. package/src/isAbsolutePath.test.ts +1 -1
  35. package/src/loadProject.test.ts +206 -75
  36. package/src/loadProject.ts +61 -31
  37. package/src/migrations/migrateToDirectory.test.ts +54 -0
  38. package/src/migrations/migrateToDirectory.ts +59 -0
  39. package/src/resolve-modules/plugins/resolvePlugins.test.ts +2 -1
  40. package/src/resolve-modules/plugins/resolvePlugins.ts +1 -1
  41. package/src/resolve-modules/plugins/types.ts +5 -2
  42. package/src/resolve-modules/validateModuleSettings.test.ts +1 -1
@@ -8,7 +8,7 @@ import type { ProjectSettings } from "@inlang/project-settings";
8
8
  *
9
9
  * - only uses minimally required functions to decrease the API footprint on the ecosystem.
10
10
  */
11
- export type NodeishFilesystemSubset = Pick<NodeishFilesystem, "readFile" | "readdir" | "mkdir" | "writeFile">;
11
+ export type NodeishFilesystemSubset = Pick<NodeishFilesystem, "readFile" | "readdir" | "mkdir" | "writeFile" | "watch">;
12
12
  /**
13
13
  * Function that resolves (imports and initializes) the plugins.
14
14
  */
@@ -26,6 +26,7 @@ export type ResolvePluginsFunction = (args: {
26
26
  export type ResolvedPluginApi = {
27
27
  loadMessages: (args: {
28
28
  settings: ProjectSettings;
29
+ nodeishFs: NodeishFilesystemSubset;
29
30
  }) => Promise<Message[]> | Message[];
30
31
  saveMessages: (args: {
31
32
  settings: ProjectSettings;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/resolve-modules/plugins/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AACnD,OAAO,KAAK,EACX,mCAAmC,EACnC,6CAA6C,EAC7C,6CAA6C,EAC7C,uBAAuB,EACvB,2BAA2B,EAC3B,0CAA0C,EAC1C,MAAM,aAAa,CAAA;AACpB,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAA;AAC9C,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAA;AACzE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAA;AAE/D;;;;GAIG;AACH,MAAM,MAAM,uBAAuB,GAAG,IAAI,CACzC,iBAAiB,EACjB,UAAU,GAAG,SAAS,GAAG,OAAO,GAAG,WAAW,CAC9C,CAAA;AAED;;GAEG;AACH,MAAM,MAAM,sBAAsB,GAAG,CAAC,IAAI,EAAE;IAC3C,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,CAAA;IACtB,QAAQ,EAAE,eAAe,CAAA;IACzB,SAAS,EAAE,uBAAuB,CAAA;CAClC,KAAK,OAAO,CAAC;IACb,IAAI,EAAE,iBAAiB,CAAA;IACvB,MAAM,EAAE,KAAK,CACV,mCAAmC,GACnC,6CAA6C,GAC7C,6CAA6C,GAC7C,uBAAuB,GACvB,2BAA2B,GAC3B,0CAA0C,CAC5C,CAAA;CACD,CAAC,CAAA;AAEF;;GAEG;AACH,MAAM,MAAM,iBAAiB,GAAG;IAC/B,YAAY,EAAE,CAAC,IAAI,EAAE;QAAE,QAAQ,EAAE,eAAe,CAAA;KAAE,KAAK,OAAO,CAAC,OAAO,EAAE,CAAC,GAAG,OAAO,EAAE,CAAA;IACrF,YAAY,EAAE,CAAC,IAAI,EAAE;QAAE,QAAQ,EAAE,eAAe,CAAC;QAAC,QAAQ,EAAE,OAAO,EAAE,CAAA;KAAE,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAA;IAChG;;;;;;;;;;;;;;;;OAgBG;IACH,SAAS,EAAE,MAAM,CAAC,OAAO,MAAM,IAAI,MAAM,EAAE,GAAG,WAAW,MAAM,IAAI,MAAM,EAAE,EAAE,OAAO,CAAC,GAAG;QACvF,yBAAyB,CAAC,EAAE,2BAA2B,CAAA;KACvD,CAAA;CACD,CAAA"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/resolve-modules/plugins/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AACnD,OAAO,KAAK,EACX,mCAAmC,EACnC,6CAA6C,EAC7C,6CAA6C,EAC7C,uBAAuB,EACvB,2BAA2B,EAC3B,0CAA0C,EAC1C,MAAM,aAAa,CAAA;AACpB,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAA;AAC9C,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAA;AACzE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAA;AAE/D;;;;GAIG;AACH,MAAM,MAAM,uBAAuB,GAAG,IAAI,CACzC,iBAAiB,EACjB,UAAU,GAAG,SAAS,GAAG,OAAO,GAAG,WAAW,GAAG,OAAO,CACxD,CAAA;AAED;;GAEG;AACH,MAAM,MAAM,sBAAsB,GAAG,CAAC,IAAI,EAAE;IAC3C,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,CAAA;IACtB,QAAQ,EAAE,eAAe,CAAA;IACzB,SAAS,EAAE,uBAAuB,CAAA;CAClC,KAAK,OAAO,CAAC;IACb,IAAI,EAAE,iBAAiB,CAAA;IACvB,MAAM,EAAE,KAAK,CACV,mCAAmC,GACnC,6CAA6C,GAC7C,6CAA6C,GAC7C,uBAAuB,GACvB,2BAA2B,GAC3B,0CAA0C,CAC5C,CAAA;CACD,CAAC,CAAA;AAEF;;GAEG;AACH,MAAM,MAAM,iBAAiB,GAAG;IAC/B,YAAY,EAAE,CAAC,IAAI,EAAE;QACpB,QAAQ,EAAE,eAAe,CAAA;QACzB,SAAS,EAAE,uBAAuB,CAAA;KAClC,KAAK,OAAO,CAAC,OAAO,EAAE,CAAC,GAAG,OAAO,EAAE,CAAA;IACpC,YAAY,EAAE,CAAC,IAAI,EAAE;QAAE,QAAQ,EAAE,eAAe,CAAC;QAAC,QAAQ,EAAE,OAAO,EAAE,CAAA;KAAE,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAA;IAChG;;;;;;;;;;;;;;;;OAgBG;IACH,SAAS,EAAE,MAAM,CAAC,OAAO,MAAM,IAAI,MAAM,EAAE,GAAG,WAAW,MAAM,IAAI,MAAM,EAAE,EAAE,OAAO,CAAC,GAAG;QACvF,yBAAyB,CAAC,EAAE,2BAA2B,CAAA;KACvD,CAAA;CACD,CAAA"}
@@ -1,6 +1,6 @@
1
1
  /* eslint-disable @typescript-eslint/no-non-null-assertion */
2
2
  import { expect, test } from "vitest";
3
- import { Plugin, MessageLintRule } from "@inlang/sdk";
3
+ import { Plugin, MessageLintRule } from "../index.js";
4
4
  // import { createNodeishMemoryFs } from "@lix-js/fs"
5
5
  import { Type } from "@sinclair/typebox";
6
6
  import { validatedModuleSettings } from "./validatedModuleSettings.js";
package/package.json CHANGED
@@ -1,57 +1,57 @@
1
1
  {
2
- "name": "@inlang/sdk",
3
- "type": "module",
4
- "version": "0.17.0",
5
- "license": "Apache-2.0",
6
- "publishConfig": {
7
- "access": "public"
8
- },
9
- "exports": {
10
- ".": "./dist/index.js",
11
- "./test-utilities": "./dist/test-utilities/index.js",
12
- "./lint": "./dist/lint/index.js",
13
- "./messages": "./dist/messages/index.js"
14
- },
15
- "files": [
16
- "./dist",
17
- "./src"
18
- ],
19
- "scripts": {
20
- "build": "tsc --build",
21
- "dev": "tsc --watch",
22
- "test": "tsc --noEmit && vitest run --passWithNoTests --coverage",
23
- "lint": "eslint ./src --fix",
24
- "format": "prettier ./src --write",
25
- "clean": "rm -rf ./dist ./.turbo ./node_modules"
26
- },
27
- "engines": {
28
- "node": ">=18.0.0"
29
- },
30
- "dependencies": {
31
- "@inlang/json-types": "*",
32
- "@inlang/translatable": "*",
33
- "@inlang/message-lint-rule": "*",
34
- "@inlang/module": "*",
35
- "@inlang/language-tag": "*",
36
- "@inlang/message": "*",
37
- "@inlang/plugin": "*",
38
- "@inlang/project-settings": "*",
39
- "@inlang/result": "*",
40
- "@lix-js/fs": "*",
41
- "@sinclair/typebox": "^0.31.17",
42
- "deepmerge-ts": "^5.1.0",
43
- "solid-js": "1.6.12",
44
- "throttle-debounce": "5.0.0",
45
- "dedent": "1.5.1"
46
- },
47
- "devDependencies": {
48
- "@lix-js/fs": "*",
49
- "@types/throttle-debounce": "5.0.0",
50
- "@vitest/coverage-v8": "^0.33.0",
51
- "jsdom": "22.1.0",
52
- "patch-package": "6.5.1",
53
- "tsd": "^0.25.0",
54
- "typescript": "5.2.2",
55
- "vitest": "^0.33.0"
56
- }
57
- }
2
+ "name": "@inlang/sdk",
3
+ "type": "module",
4
+ "version": "0.19.0",
5
+ "license": "Apache-2.0",
6
+ "publishConfig": {
7
+ "access": "public"
8
+ },
9
+ "exports": {
10
+ ".": "./dist/index.js",
11
+ "./test-utilities": "./dist/test-utilities/index.js",
12
+ "./lint": "./dist/lint/index.js",
13
+ "./messages": "./dist/messages/index.js"
14
+ },
15
+ "files": [
16
+ "./dist",
17
+ "./src"
18
+ ],
19
+ "engines": {
20
+ "node": ">=18.0.0"
21
+ },
22
+ "dependencies": {
23
+ "@sinclair/typebox": "^0.31.17",
24
+ "deepmerge-ts": "^5.1.0",
25
+ "solid-js": "1.6.12",
26
+ "throttle-debounce": "5.0.0",
27
+ "dedent": "1.5.1",
28
+ "@inlang/json-types": "1.1.0",
29
+ "@inlang/message-lint-rule": "1.4.0",
30
+ "@inlang/translatable": "1.2.0",
31
+ "@inlang/module": "1.2.0",
32
+ "@inlang/language-tag": "1.2.0",
33
+ "@inlang/message": "2.0.0",
34
+ "@inlang/plugin": "2.4.0",
35
+ "@inlang/result": "1.1.0",
36
+ "@inlang/project-settings": "2.2.0",
37
+ "@lix-js/fs": "0.4.0"
38
+ },
39
+ "devDependencies": {
40
+ "@types/throttle-debounce": "5.0.0",
41
+ "@vitest/coverage-v8": "^0.33.0",
42
+ "jsdom": "22.1.0",
43
+ "patch-package": "6.5.1",
44
+ "tsd": "^0.25.0",
45
+ "typescript": "5.2.2",
46
+ "vitest": "^0.33.0",
47
+ "@lix-js/fs": "0.4.0"
48
+ },
49
+ "scripts": {
50
+ "build": "tsc --build",
51
+ "dev": "tsc --watch",
52
+ "test": "tsc --noEmit && vitest run --passWithNoTests --coverage",
53
+ "lint": "eslint ./src --fix",
54
+ "format": "prettier ./src --write",
55
+ "clean": "rm -rf ./dist ./node_modules"
56
+ }
57
+ }
@@ -90,11 +90,11 @@ const $import: ImportFunction = async (name) => ({
90
90
  describe("config", () => {
91
91
  it("should react to changes in config", async () => {
92
92
  const fs = createNodeishMemoryFs()
93
- await fs.mkdir("/user/project", { recursive: true })
94
- await fs.writeFile("/user/project/project.inlang.json", JSON.stringify(config))
93
+ await fs.mkdir("/user/project.inlang", { recursive: true })
94
+ await fs.writeFile("/user/project.inlang/settings.json", JSON.stringify(config))
95
95
  const project = solidAdapter(
96
96
  await loadProject({
97
- settingsFilePath: "/user/project/project.inlang.json",
97
+ projectPath: "/user/project.inlang",
98
98
  nodeishFs: fs,
99
99
  _import: $import,
100
100
  }),
@@ -123,11 +123,11 @@ describe("config", () => {
123
123
  describe("installed", () => {
124
124
  it("react to changes that are unrelated to installed items", async () => {
125
125
  const fs = createNodeishMemoryFs()
126
- await fs.mkdir("/user/project", { recursive: true })
127
- await fs.writeFile("/user/project/project.inlang.json", JSON.stringify(config))
126
+ await fs.mkdir("/user/project.inlang", { recursive: true })
127
+ await fs.writeFile("/user/project.inlang/settings.json", JSON.stringify(config))
128
128
  const project = solidAdapter(
129
129
  await loadProject({
130
- settingsFilePath: "/user/project/project.inlang.json",
130
+ projectPath: "/user/project.inlang",
131
131
  nodeishFs: fs,
132
132
  _import: $import,
133
133
  }),
@@ -188,11 +188,11 @@ describe("messages", () => {
188
188
 
189
189
  const mockImport: ImportFunction = async () => ({ default: mockPlugin })
190
190
 
191
- await fs.mkdir("/user/project", { recursive: true })
192
- await fs.writeFile("/user/project/project.inlang.json", JSON.stringify(mockConfig))
191
+ await fs.mkdir("/user/project.inlang.inlang", { recursive: true })
192
+ await fs.writeFile("/user/project.inlang.inlang/settings.json", JSON.stringify(mockConfig))
193
193
  const project = solidAdapter(
194
194
  await loadProject({
195
- settingsFilePath: "/user/project/project.inlang.json",
195
+ projectPath: "/user/project.inlang.inlang",
196
196
  nodeishFs: fs,
197
197
  _import: mockImport,
198
198
  }),
@@ -218,11 +218,11 @@ describe("messages", () => {
218
218
 
219
219
  it("should react to changes in messages", async () => {
220
220
  const fs = createNodeishMemoryFs()
221
- await fs.mkdir("/user/project", { recursive: true })
222
- await fs.writeFile("/user/project/project.inlang.json", JSON.stringify(config))
221
+ await fs.mkdir("/user/project.inlang.inlang", { recursive: true })
222
+ await fs.writeFile("/user/project.inlang.inlang/settings.json", JSON.stringify(config))
223
223
  const project = solidAdapter(
224
224
  await loadProject({
225
- settingsFilePath: "/user/project/project.inlang.json",
225
+ projectPath: "/user/project.inlang.inlang",
226
226
  nodeishFs: fs,
227
227
  _import: $import,
228
228
  }),
@@ -280,10 +280,11 @@ describe("lint", () => {
280
280
  it.todo("should react to changes in config", async () => {
281
281
  await createRoot(async () => {
282
282
  const fs = createNodeishMemoryFs()
283
- await fs.writeFile("./project.config.json", JSON.stringify(config))
283
+ await fs.mkdir("./project.inlang", { recursive: true })
284
+ await fs.writeFile("./project.inlang/settings.json", JSON.stringify(config))
284
285
  const project = solidAdapter(
285
286
  await loadProject({
286
- settingsFilePath: "./project.config.json",
287
+ projectPath: "./project.inlang",
287
288
  nodeishFs: fs,
288
289
  _import: $import,
289
290
  }),
@@ -321,7 +322,7 @@ describe("lint", () => {
321
322
  await fs.writeFile("./project.config.json", JSON.stringify(config))
322
323
  const project = solidAdapter(
323
324
  await loadProject({
324
- settingsFilePath: "./project.config.json",
325
+ projectPath: "./project.config.json",
325
326
  nodeishFs: fs,
326
327
  _import: $import,
327
328
  }),
@@ -2,16 +2,16 @@ import { it, expect, vi } from "vitest"
2
2
  import { createNodeishFsWithAbsolutePaths } from "./createNodeishFsWithAbsolutePaths.js"
3
3
  import type { NodeishFilesystemSubset } from "./versionedInterfaces.js"
4
4
 
5
- it("throws an error if settingsFilePath is not an absolute path", () => {
5
+ it("throws an error if projectPath is not an absolute path", () => {
6
6
  const relativePath = "relative/path"
7
7
 
8
8
  expect(() =>
9
- createNodeishFsWithAbsolutePaths({ settingsFilePath: relativePath, nodeishFs: {} as any })
9
+ createNodeishFsWithAbsolutePaths({ projectPath: relativePath, nodeishFs: {} as any })
10
10
  ).toThrow()
11
11
  })
12
12
 
13
13
  it("intercepts paths correctly for readFile", async () => {
14
- const settingsFilePath = `/Users/samuel/Documents/paraglide/example/project.inlang.json`
14
+ const projectPath = `/Users/samuel/Documents/paraglide/example/project.inlang`
15
15
 
16
16
  const filePaths = [
17
17
  ["file.txt", `/Users/samuel/Documents/paraglide/example/file.txt`],
@@ -28,10 +28,11 @@ it("intercepts paths correctly for readFile", async () => {
28
28
  readdir: vi.fn(),
29
29
  mkdir: vi.fn(),
30
30
  writeFile: vi.fn(),
31
+ watch: vi.fn(),
31
32
  } satisfies Record<keyof NodeishFilesystemSubset, any>
32
33
 
33
34
  const interceptedFs = createNodeishFsWithAbsolutePaths({
34
- settingsFilePath,
35
+ projectPath,
35
36
  nodeishFs: mockNodeishFs,
36
37
  })
37
38
 
@@ -6,19 +6,19 @@ import { isAbsolutePath } from "./isAbsolutePath.js"
6
6
  * Wraps the nodeish filesystem subset with a function that intercepts paths
7
7
  * and prepends the base path.
8
8
  *
9
- * The paths are resolved from the `settingsFilePath` argument.
9
+ * The paths are resolved from the `projectPath` argument.
10
10
  */
11
11
  export const createNodeishFsWithAbsolutePaths = (args: {
12
- settingsFilePath: string
12
+ projectPath: string
13
13
  nodeishFs: NodeishFilesystemSubset
14
14
  }): NodeishFilesystemSubset => {
15
- if (!isAbsolutePath(args.settingsFilePath)) {
16
- throw new Error(`Expected an absolute path but received "${args.settingsFilePath}".`)
15
+ if (!isAbsolutePath(args.projectPath)) {
16
+ throw new Error(`Expected an absolute path but received "${args.projectPath}".`)
17
17
  }
18
18
 
19
19
  // get the base path of the settings file by
20
20
  // removing the file name from the path
21
- const basePath = normalizePath(args.settingsFilePath).split("/").slice(0, -1).join("/")
21
+ const basePath = normalizePath(args.projectPath).split("/").slice(0, -1).join("/")
22
22
 
23
23
  const makeAbsolute = (path: string) => {
24
24
  if (isAbsolutePath(path)) {
@@ -35,5 +35,9 @@ export const createNodeishFsWithAbsolutePaths = (args: {
35
35
  readdir: (path: string) => args.nodeishFs.readdir(makeAbsolute(path)),
36
36
  mkdir: (path: string) => args.nodeishFs.mkdir(makeAbsolute(path)),
37
37
  writeFile: (path: string, data: string) => args.nodeishFs.writeFile(makeAbsolute(path), data),
38
+ watch: (
39
+ path: string,
40
+ options: { signal: AbortSignal | undefined; recursive: boolean | undefined }
41
+ ) => args.nodeishFs.watch(makeAbsolute(path), options),
38
42
  }
39
43
  }
@@ -0,0 +1,40 @@
1
+ import { createNodeishMemoryFs } from "@lix-js/fs"
2
+ import { describe, it, expect } from "vitest"
3
+ import { createNodeishFsWithWatcher } from "./createNodeishFsWithWatcher.js"
4
+
5
+ describe("watcher", () => {
6
+ it("should trigger the update function when file changes", async () => {
7
+ let counter = 0
8
+ const fs = createNodeishFsWithWatcher({
9
+ nodeishFs: createNodeishMemoryFs(),
10
+ updateMessages: () => {
11
+ counter++
12
+ },
13
+ })
14
+
15
+ // establish watcher
16
+ await fs.writeFile("file.txt", "a")
17
+ await fs.readFile("file.txt", { encoding: "utf-8" })
18
+ expect(counter).toBe(0)
19
+
20
+ // initial file change
21
+ await fs.writeFile("file.txt", "b")
22
+ await new Promise((resolve) => setTimeout(resolve, 0))
23
+
24
+ expect(counter).toBe(1)
25
+
26
+ // change file
27
+ await fs.writeFile("file.txt", "a")
28
+ await new Promise((resolve) => setTimeout(resolve, 0))
29
+
30
+ //check if update function was called
31
+ expect(counter).toBe(2)
32
+
33
+ // change file
34
+ await fs.readFile("file.txt")
35
+ await new Promise((resolve) => setTimeout(resolve, 0))
36
+
37
+ //check if update function was called
38
+ expect(counter).toBe(2)
39
+ })
40
+ })
@@ -0,0 +1,58 @@
1
+ import type { NodeishFilesystemSubset } from "@inlang/plugin"
2
+
3
+ /**
4
+ * Wraps the nodeish filesystem subset with a function that intercepts paths
5
+ * and prepends the base path.
6
+ *
7
+ * The paths are resolved from the `projectPath` argument.
8
+ */
9
+ export const createNodeishFsWithWatcher = (args: {
10
+ nodeishFs: NodeishFilesystemSubset
11
+ updateMessages: () => void
12
+ }): NodeishFilesystemSubset => {
13
+ const pathList: string[] = []
14
+
15
+ const makeWatcher = (path: string) => {
16
+ const abortController = new AbortController()
17
+ ;(async () => {
18
+ try {
19
+ const watcher = args.nodeishFs.watch(path, {
20
+ signal: abortController.signal,
21
+ persistent: false,
22
+ })
23
+ if (watcher) {
24
+ //eslint-disable-next-line @typescript-eslint/no-unused-vars
25
+ for await (const event of watcher) {
26
+ args.updateMessages()
27
+ }
28
+ }
29
+ } catch (err: any) {
30
+ if (err.name === "AbortError") return
31
+ // https://github.com/inlang/monorepo/issues/1647
32
+ // the file does not exist (yet)
33
+ // this is not testable beacause the fs.watch api differs
34
+ // from node and lix. lenghty
35
+ else if (err.code === "ENOENT") return
36
+ throw err
37
+ }
38
+ })()
39
+ }
40
+
41
+ const readFileAndExtractPath = (path: string, options: { encoding: "utf-8" | "binary" }) => {
42
+ if (!pathList.includes(path)) {
43
+ makeWatcher(path)
44
+ pathList.push(path)
45
+ }
46
+ return args.nodeishFs.readFile(path, options)
47
+ }
48
+
49
+ return {
50
+ // @ts-expect-error
51
+ readFile: (path: string, options: { encoding: "utf-8" | "binary" }) =>
52
+ readFileAndExtractPath(path, options),
53
+ readdir: args.nodeishFs.readdir,
54
+ mkdir: args.nodeishFs.mkdir,
55
+ writeFile: args.nodeishFs.writeFile,
56
+ watch: args.nodeishFs.watch,
57
+ }
58
+ }
@@ -10,7 +10,7 @@ describe("isAbsolutePath", () => {
10
10
 
11
11
  it("should correctly identify Windows absolute paths", () => {
12
12
  assert.isTrue(isAbsolutePath("C:\\Users\\User\\Documents\\File.txt"))
13
- assert.isTrue(isAbsolutePath("C:/Users/user/project/project.inlang.json"))
13
+ assert.isTrue(isAbsolutePath("C:/Users/user/project.inlang/settings.json"))
14
14
  assert.isFalse(isAbsolutePath("Projects\\Project1\\source\\file.txt"))
15
15
  })
16
16