@inlang/sdk 0.34.3 → 0.34.4

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.
@@ -0,0 +1,109 @@
1
+ import {} from "@lix-js/fs";
2
+ import _debug from "debug";
3
+ const debug = _debug("sdk:acquireFileLock");
4
+ const maxRetries = 10;
5
+ const nProbes = 50;
6
+ const probeInterval = 100;
7
+ export async function acquireFileLock(fs, lockDirPath, lockOrigin, tryCount = 0) {
8
+ if (tryCount > maxRetries) {
9
+ throw new Error(lockOrigin + " exceeded maximum Retries (5) to acquire lockfile " + tryCount);
10
+ }
11
+ try {
12
+ debug(lockOrigin + " tries to acquire a lockfile Retry Nr.: " + tryCount);
13
+ await fs.mkdir(lockDirPath);
14
+ const stats = await fs.stat(lockDirPath);
15
+ debug(lockOrigin + " acquired a lockfile Retry Nr.: " + tryCount);
16
+ return stats.mtimeMs;
17
+ }
18
+ catch (error) {
19
+ if (error.code !== "EEXIST") {
20
+ // we only expect the error that the file exists already (locked by other process)
21
+ throw error;
22
+ }
23
+ }
24
+ let currentLockTime;
25
+ try {
26
+ const stats = await fs.stat(lockDirPath);
27
+ currentLockTime = stats.mtimeMs;
28
+ }
29
+ catch (fstatError) {
30
+ if (fstatError.code === "ENOENT") {
31
+ // lock file seems to be gone :) - lets try again
32
+ debug(lockOrigin + " tryCount++ lock file seems to be gone :) - lets try again " + tryCount);
33
+ return acquireFileLock(fs, lockDirPath, lockOrigin, tryCount + 1);
34
+ }
35
+ throw fstatError;
36
+ }
37
+ debug(lockOrigin +
38
+ " tries to acquire a lockfile - lock currently in use... starting probe phase " +
39
+ tryCount);
40
+ return new Promise((resolve, reject) => {
41
+ let probeCounts = 0;
42
+ const scheduleProbationTimeout = () => {
43
+ setTimeout(async () => {
44
+ probeCounts += 1;
45
+ let lockFileStats = undefined;
46
+ try {
47
+ debug(lockOrigin + " tries to acquire a lockfile - check if the lock is free now " + tryCount);
48
+ // alright lets give it another try
49
+ lockFileStats = await fs.stat(lockDirPath);
50
+ }
51
+ catch (fstatError) {
52
+ if (fstatError.code === "ENOENT") {
53
+ debug(lockOrigin +
54
+ " tryCount++ in Promise - tries to acquire a lockfile - lock file seems to be free now - try to acquire " +
55
+ tryCount);
56
+ const lock = acquireFileLock(fs, lockDirPath, lockOrigin, tryCount + 1);
57
+ return resolve(lock);
58
+ }
59
+ return reject(fstatError);
60
+ }
61
+ // still the same locker! -
62
+ if (lockFileStats.mtimeMs === currentLockTime) {
63
+ if (probeCounts >= nProbes) {
64
+ // ok maximum lock time ran up (we waitetd nProbes * probeInterval) - we consider the lock to be stale
65
+ debug(lockOrigin +
66
+ " tries to acquire a lockfile - lock not free - but stale lets drop it" +
67
+ tryCount);
68
+ try {
69
+ await fs.rmdir(lockDirPath);
70
+ }
71
+ catch (rmLockError) {
72
+ if (rmLockError.code === "ENOENT") {
73
+ // lock already gone?
74
+ // Option 1: The "stale process" decided to get rid of it
75
+ // Option 2: Another process acquiring the lock and detected a stale one as well
76
+ }
77
+ return reject(rmLockError);
78
+ }
79
+ try {
80
+ debug(lockOrigin +
81
+ " tryCount++ same locker - try to acquire again after removing stale lock " +
82
+ tryCount);
83
+ const lock = await acquireFileLock(fs, lockDirPath, lockOrigin, tryCount + 1);
84
+ return resolve(lock);
85
+ }
86
+ catch (lockAquireException) {
87
+ return reject(lockAquireException);
88
+ }
89
+ }
90
+ else {
91
+ // lets schedule a new probation
92
+ return scheduleProbationTimeout();
93
+ }
94
+ }
95
+ else {
96
+ try {
97
+ debug(lockOrigin + " tryCount++ different locker - try to acquire again " + tryCount);
98
+ const lock = await acquireFileLock(fs, lockDirPath, lockOrigin, tryCount + 1);
99
+ return resolve(lock);
100
+ }
101
+ catch (error) {
102
+ return reject(error);
103
+ }
104
+ }
105
+ }, probeInterval);
106
+ };
107
+ scheduleProbationTimeout();
108
+ });
109
+ }
@@ -0,0 +1,3 @@
1
+ import { type NodeishFilesystem } from "@lix-js/fs";
2
+ export declare function releaseLock(fs: NodeishFilesystem, lockDirPath: string, lockOrigin: string, lockTime: number): Promise<void>;
3
+ //# sourceMappingURL=releaseLock.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"releaseLock.d.ts","sourceRoot":"","sources":["../../../src/persistence/filelock/releaseLock.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,iBAAiB,EAAE,MAAM,YAAY,CAAA;AAInD,wBAAsB,WAAW,CAChC,EAAE,EAAE,iBAAiB,EACrB,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,iBAmBhB"}
@@ -0,0 +1,23 @@
1
+ import {} from "@lix-js/fs";
2
+ import _debug from "debug";
3
+ const debug = _debug("sdk:releaseLock");
4
+ export async function releaseLock(fs, lockDirPath, lockOrigin, lockTime) {
5
+ debug(lockOrigin + " releasing the lock ");
6
+ try {
7
+ const stats = await fs.stat(lockDirPath);
8
+ if (stats.mtimeMs === lockTime) {
9
+ // this can be corrupt as welll since the last getStat and the current a modification could have occured :-/
10
+ await fs.rmdir(lockDirPath);
11
+ }
12
+ }
13
+ catch (statError) {
14
+ debug(lockOrigin + " couldn't release the lock");
15
+ if (statError.code === "ENOENT") {
16
+ // ok seeks like the log was released by someone else
17
+ debug(lockOrigin + " WARNING - the lock was released by a different process");
18
+ return;
19
+ }
20
+ debug(statError);
21
+ throw statError;
22
+ }
23
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@inlang/sdk",
3
3
  "type": "module",
4
- "version": "0.34.3",
4
+ "version": "0.34.4",
5
5
  "license": "Apache-2.0",
6
6
  "publishConfig": {
7
7
  "access": "public"
@@ -32,14 +32,14 @@
32
32
  "murmurhash3js": "^3.0.1",
33
33
  "solid-js": "1.6.12",
34
34
  "throttle-debounce": "^5.0.0",
35
- "@inlang/json-types": "1.1.0",
36
35
  "@inlang/language-tag": "1.5.1",
37
- "@inlang/message": "2.1.0",
36
+ "@inlang/json-types": "1.1.0",
38
37
  "@inlang/message-lint-rule": "1.4.7",
39
- "@inlang/module": "1.2.11",
40
38
  "@inlang/project-settings": "2.4.2",
41
- "@inlang/result": "1.1.0",
42
39
  "@inlang/plugin": "2.4.11",
40
+ "@inlang/message": "2.1.0",
41
+ "@inlang/result": "1.1.0",
42
+ "@inlang/module": "1.2.11",
43
43
  "@inlang/translatable": "1.3.1",
44
44
  "@lix-js/client": "1.4.0",
45
45
  "@lix-js/fs": "1.0.0"
@@ -232,7 +232,7 @@ describe("messages", () => {
232
232
  // TODO: how can we await `setConfig` correctly
233
233
  await new Promise((resolve) => setTimeout(resolve, 510))
234
234
 
235
- expect(effectOnMessagesCounter).toBe(1) // 2 times because effect creation + set
235
+ expect(effectOnMessagesCounter).toBe(7) // 7 = initial effect, setSetting, loadMessage (2x - one per message), setResolvedPlugins, loadMessages (2x - one per message)
236
236
  expect(Object.values(project.query.messages.getAll()).length).toBe(2)
237
237
  })
238
238
 
@@ -2,15 +2,72 @@
2
2
  import { describe, it, expect } from "vitest"
3
3
  import { createMessagesQuery } from "./createMessagesQuery.js"
4
4
  import { createEffect, createRoot, createSignal } from "./reactivity/solid.js"
5
- import type { Message, Text } from "@inlang/message"
5
+ import { Message, type Text } from "@inlang/message"
6
6
  import { createMessage } from "./test-utilities/createMessage.js"
7
+ import { createNodeishMemoryFs } from "@lix-js/fs"
8
+ import type { resolveModules } from "./resolve-modules/resolveModules.js"
9
+ import type { ProjectSettings } from "./versionedInterfaces.js"
10
+ import type { InlangProject } from "./api.js"
7
11
 
8
12
  const createChangeListener = async (cb: () => void) => createEffect(cb)
9
13
  const nextTick = () => new Promise((resolve) => setTimeout(resolve, 0))
10
14
 
11
- describe("create", () => {
12
- it("should create a message", () => {
13
- const query = createMessagesQuery(() => [])
15
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
16
+ const awaitableCreateMessageQuery = async (_messages: () => Message[]) => {
17
+ const fs = createNodeishMemoryFs()
18
+ const settings: ProjectSettings = {
19
+ sourceLanguageTag: "en",
20
+ languageTags: ["en"],
21
+ modules: ["plugin.js", "lintRule.js"],
22
+ messageLintRuleLevels: {
23
+ "messageLintRule.project.missingTranslation": "error",
24
+ },
25
+ "plugin.project.i18next": {
26
+ pathPattern: "./examples/example01/{languageTag}.json",
27
+ variableReferencePattern: ["{", "}"],
28
+ },
29
+ }
30
+
31
+ let messages: any = _messages()
32
+
33
+ const resolvedModules: Awaited<ReturnType<typeof resolveModules>> = {
34
+ meta: [],
35
+ plugins: [],
36
+ messageLintRules: [],
37
+ resolvedPluginApi: {
38
+ loadMessages: (() => {
39
+ return messages
40
+ }) as any,
41
+ saveMessages: ((newMessages: any) => {
42
+ messages = newMessages
43
+ }) as any,
44
+ customApi: {},
45
+ },
46
+ errors: [],
47
+ }
48
+
49
+ return new Promise<InlangProject["query"]["messages"]>((res, rej) => {
50
+ const query = createMessagesQuery({
51
+ projectPath: "",
52
+ nodeishFs: fs,
53
+ settings: () => settings,
54
+ resolvedModules: () => resolvedModules,
55
+ onInitialMessageLoadResult: (error) => {
56
+ if (error) {
57
+ rej(error)
58
+ } else {
59
+ res(query)
60
+ }
61
+ },
62
+ onLoadMessageResult: () => {},
63
+ onSaveMessageResult: () => {},
64
+ })
65
+ })
66
+ }
67
+
68
+ describe("create", async () => {
69
+ it("should create a message", async () => {
70
+ const query = await awaitableCreateMessageQuery(() => [])
14
71
  expect(query.get({ where: { id: "first-message" } })).toBeUndefined()
15
72
 
16
73
  const mockMessage = createMessage("first-message", { en: "Hello World" })
@@ -20,8 +77,8 @@ describe("create", () => {
20
77
  expect(created).toBe(true)
21
78
  })
22
79
 
23
- it("query.getByDefaultAlias should return a message with a default alias", () => {
24
- const query = createMessagesQuery(() => [])
80
+ it("query.getByDefaultAlias should return a message with a default alias", async () => {
81
+ const query = await awaitableCreateMessageQuery(() => [])
25
82
  expect(query.get({ where: { id: "first-message" } })).toBeUndefined()
26
83
 
27
84
  const mockMessage = createMessage("first-message", { en: "Hello World" })
@@ -33,8 +90,10 @@ describe("create", () => {
33
90
  expect(created).toBe(true)
34
91
  })
35
92
 
36
- it("should return false if message with id already exists", () => {
37
- const query = createMessagesQuery(() => [createMessage("first-message", { en: "Hello World" })])
93
+ it("should return false if message with id already exists", async () => {
94
+ const query = await awaitableCreateMessageQuery(() => [
95
+ createMessage("first-message", { en: "Hello World" }),
96
+ ])
38
97
  expect(query.get({ where: { id: "first-message" } })).toBeDefined()
39
98
 
40
99
  const mockMessage = createMessage("first-message", { en: "Some Text" })
@@ -45,23 +104,35 @@ describe("create", () => {
45
104
  })
46
105
  })
47
106
 
48
- describe("get", () => {
49
- it("should return undefined if a message does not exist", () => {
50
- const query = createMessagesQuery(() => [createMessage("first-message", { en: "Hello World" })])
107
+ describe("get", async () => {
108
+ it("should return undefined if a message does not exist", async () => {
109
+ const query = await awaitableCreateMessageQuery(() => [
110
+ createMessage("first-message", { en: "Hello World" }),
111
+ ])
112
+
51
113
  const message = query.get({ where: { id: "none-existent-message" } })
52
114
  expect(message).toBeUndefined()
53
115
  })
54
116
 
55
- it("should return an object, not an array", () => {
56
- const query = createMessagesQuery(() => [createMessage("first-message", { en: "Hello World" })])
117
+ it("should return an object, not an array", async () => {
118
+ const query = await awaitableCreateMessageQuery(() => [
119
+ createMessage("first-message", { en: "Hello World" }),
120
+ ])
121
+ expect(query.get({ where: { id: "first-message" } })).toBeDefined()
122
+
123
+ const mockMessageInit = createMessage("first-message", { en: "Hello World" })
124
+ query.create({ data: mockMessageInit })
125
+
57
126
  const message = query.get({ where: { id: "first-message" } })
58
127
  expect(message).toBeDefined()
59
128
  expect(Array.isArray(message)).toBe(false)
60
129
  })
61
130
 
62
131
  // todo: improve the readonly type
63
- it.skip("mutating the returned value should not affect subsequent return values", () => {
64
- const query = createMessagesQuery(() => [createMessage("first-message", { en: "Hello World" })])
132
+ it.skip("mutating the returned value should not affect subsequent return values", async () => {
133
+ const query = await awaitableCreateMessageQuery(() => [
134
+ createMessage("first-message", { en: "Hello World" }),
135
+ ])
65
136
  const message1 = query.get({ where: { id: "first-message" } })!
66
137
  ;(message1.variants.find((v) => v.languageTag === "en")!.pattern![0]! as Text).value =
67
138
  "Hello World 2"
@@ -76,16 +147,16 @@ describe("get", () => {
76
147
  })
77
148
  })
78
149
 
79
- describe("getAll", () => {
80
- it("should return an empty array if no messages exist", () => {
81
- const query = createMessagesQuery(() => [])
150
+ describe("getAll", async () => {
151
+ it("should return an empty array if no messages exist", async () => {
152
+ const query = await awaitableCreateMessageQuery(() => [])
82
153
  const messages = query.getAll()
83
154
 
84
155
  expect(Object.values(messages!)).toEqual([])
85
156
  })
86
157
 
87
- it("should return all message objects", () => {
88
- const query = createMessagesQuery(() => [])
158
+ it("should return all message objects", async () => {
159
+ const query = await awaitableCreateMessageQuery(() => [])
89
160
  const mockMessage1 = createMessage("first-message", { en: "Hello World" })
90
161
  const mockMessage2 = createMessage("second-message", { en: "Hello World 2" })
91
162
  query.create({ data: mockMessage1 })
@@ -96,8 +167,11 @@ describe("getAll", () => {
96
167
  })
97
168
 
98
169
  // todo: improve the readonly type
99
- it.skip("mutating the returned value should not affect subsequent return values", () => {
100
- const query = createMessagesQuery(() => [createMessage("first-message", { en: "Hello World" })])
170
+ it.skip("mutating the returned value should not affect subsequent return values", async () => {
171
+ const query = await awaitableCreateMessageQuery(() => [
172
+ createMessage("first-message", { en: "Hello World" }),
173
+ ])
174
+
101
175
  const messages1 = query.getAll()
102
176
  ;(
103
177
  Object.values(messages1!)[0]!.variants.find((v) => v.languageTag === "en")!
@@ -113,9 +187,12 @@ describe("getAll", () => {
113
187
  })
114
188
  })
115
189
 
116
- describe("update", () => {
117
- it("should update a message", () => {
118
- const query = createMessagesQuery(() => [createMessage("first-message", { en: "Hello World" })])
190
+ describe("update", async () => {
191
+ it("should update a message", async () => {
192
+ const query = await awaitableCreateMessageQuery(() => [
193
+ createMessage("first-message", { en: "Hello World" }),
194
+ ])
195
+
119
196
  expect(query.get({ where: { id: "first-message" } })).toBeDefined()
120
197
 
121
198
  const mockMessage = createMessage("first-message", { en: "Hello World 2" })
@@ -125,8 +202,8 @@ describe("update", () => {
125
202
  expect(updated).toBe(true)
126
203
  })
127
204
 
128
- it("should return false if message with id does not exist exists", () => {
129
- const query = createMessagesQuery(() => [])
205
+ it("should return false if message with id does not exist exists", async () => {
206
+ const query = await awaitableCreateMessageQuery(() => [])
130
207
  expect(query.get({ where: { id: "first-message" } })).toBeUndefined()
131
208
 
132
209
  const mockMessage = createMessage("first-message", { en: "Hello World" })
@@ -135,9 +212,9 @@ describe("update", () => {
135
212
  })
136
213
  })
137
214
 
138
- describe("upsert", () => {
139
- it("should create a message if not present yet", () => {
140
- const query = createMessagesQuery(() => [])
215
+ describe("upsert", async () => {
216
+ it("should create a message if not present yet", async () => {
217
+ const query = await awaitableCreateMessageQuery(() => [])
141
218
  expect(query.get({ where: { id: "first-message" } })).toBeUndefined()
142
219
 
143
220
  const mockMessage = createMessage("first-message", { en: "Hello World" })
@@ -147,8 +224,15 @@ describe("upsert", () => {
147
224
  expect(upserted).toBe(true)
148
225
  })
149
226
 
150
- it("should update message if id already exists", () => {
151
- const query = createMessagesQuery(() => [createMessage("first-message", { en: "Hello World" })])
227
+ it("should update message if id already exists", async () => {
228
+ const query = await awaitableCreateMessageQuery(() => [
229
+ createMessage("first-message", { en: "Hello World" }),
230
+ ])
231
+ expect(query.get({ where: { id: "first-message" } })).toBeDefined()
232
+
233
+ const mockMessageInit = createMessage("first-message", { en: "Hello World" })
234
+ query.create({ data: mockMessageInit })
235
+
152
236
  expect(query.get({ where: { id: "first-message" } })).toBeDefined()
153
237
 
154
238
  const mockMessage = createMessage("first-message", { en: "Hello World 2" })
@@ -159,9 +243,12 @@ describe("upsert", () => {
159
243
  })
160
244
  })
161
245
 
162
- describe("delete", () => {
163
- it("should delete a message", () => {
164
- const query = createMessagesQuery(() => [createMessage("first-message", { en: "Hello World" })])
246
+ describe("delete", async () => {
247
+ it("should delete a message", async () => {
248
+ const query = await awaitableCreateMessageQuery(() => [
249
+ createMessage("first-message", { en: "Hello World" }),
250
+ ])
251
+
165
252
  expect(query.get({ where: { id: "first-message" } })).toBeDefined()
166
253
 
167
254
  const deleted = query.delete({ where: { id: "first-message" } })
@@ -170,8 +257,8 @@ describe("delete", () => {
170
257
  expect(deleted).toBe(true)
171
258
  })
172
259
 
173
- it("should return false if message with id does not exist", () => {
174
- const query = createMessagesQuery(() => [])
260
+ it("should return false if message with id does not exist", async () => {
261
+ const query = await awaitableCreateMessageQuery(() => [])
175
262
  expect(query.get({ where: { id: "first-message" } })).toBeUndefined()
176
263
 
177
264
  const deleted = query.delete({ where: { id: "first-message" } })
@@ -179,11 +266,11 @@ describe("delete", () => {
179
266
  })
180
267
  })
181
268
 
182
- describe("reactivity", () => {
183
- describe("get", () => {
269
+ describe("reactivity", async () => {
270
+ describe("get", async () => {
184
271
  it("should react to `create`", async () => {
185
272
  await createRoot(async () => {
186
- const query = createMessagesQuery(() => [])
273
+ const query = await awaitableCreateMessageQuery(() => [])
187
274
 
188
275
  // eslint-disable-next-line unicorn/no-null
189
276
  let message: Message | undefined | null = null
@@ -201,7 +288,9 @@ describe("reactivity", () => {
201
288
 
202
289
  it("should react to `update`", async () => {
203
290
  await createRoot(async () => {
204
- const query = createMessagesQuery(() => [createMessage("1", { en: "before" })])
291
+ const query = await awaitableCreateMessageQuery(() => [
292
+ createMessage("1", { en: "before" }),
293
+ ])
205
294
 
206
295
  let message: Message | undefined
207
296
  await createChangeListener(() => (message = query.get({ where: { id: "1" } })))
@@ -221,7 +310,7 @@ describe("reactivity", () => {
221
310
 
222
311
  it("should react to `upsert`", async () => {
223
312
  await createRoot(async () => {
224
- const query = createMessagesQuery(() => [])
313
+ const query = await awaitableCreateMessageQuery(() => [])
225
314
 
226
315
  let message: Message | undefined
227
316
  await createChangeListener(() => (message = query.get({ where: { id: "1" } })))
@@ -244,7 +333,7 @@ describe("reactivity", () => {
244
333
 
245
334
  it("should react to `delete`", async () => {
246
335
  await createRoot(async () => {
247
- const query = createMessagesQuery(() => [createMessage("1", { en: "" })])
336
+ const query = await awaitableCreateMessageQuery(() => [createMessage("1", { en: "" })])
248
337
 
249
338
  let message: Message | undefined
250
339
  await createChangeListener(() => (message = query.get({ where: { id: "1" } })))
@@ -254,37 +343,13 @@ describe("reactivity", () => {
254
343
  expect(message).toBeUndefined()
255
344
  })
256
345
  })
257
-
258
- it("should react to changes to the input `messages`", async () => {
259
- const [messages, setMessages] = createSignal<Message[]>([])
260
- const query = createMessagesQuery(messages)
261
-
262
- // eslint-disable-next-line unicorn/no-null
263
- let message: Message | undefined | null = null
264
- await createChangeListener(() => (message = query.get({ where: { id: "1" } })))
265
- expect(message).toBeUndefined()
266
-
267
- query.create({ data: createMessage("1", { en: "before" }) })
268
- expect(message).toBeDefined()
269
- expect(
270
- (message!.variants.find((variant) => variant.languageTag === "en")?.pattern[0] as Text)
271
- .value
272
- ).toBe("before")
273
-
274
- setMessages([createMessage("1", { en: "after" })])
275
- expect(message).toBeDefined()
276
- expect(
277
- (message!.variants.find((variant) => variant.languageTag === "en")?.pattern[0] as Text)
278
- .value
279
- ).toBe("after")
280
- })
281
346
  })
282
347
 
283
- describe("subscribe", () => {
284
- describe("get", () => {
348
+ describe("subscribe", async () => {
349
+ describe("get", async () => {
285
350
  it("should subscribe to `create`", async () => {
286
351
  await createRoot(async () => {
287
- const query = createMessagesQuery(() => [])
352
+ const query = await awaitableCreateMessageQuery(() => [])
288
353
 
289
354
  // eslint-disable-next-line unicorn/no-null
290
355
  let message: Message | undefined | null = null
@@ -299,10 +364,10 @@ describe("reactivity", () => {
299
364
  })
300
365
  })
301
366
  })
302
- describe("getByDefaultAlias", () => {
367
+ describe("getByDefaultAlias", async () => {
303
368
  it("should subscribe to `create`", async () => {
304
369
  await createRoot(async () => {
305
- const query = createMessagesQuery(() => [])
370
+ const query = await awaitableCreateMessageQuery(() => [])
306
371
 
307
372
  // eslint-disable-next-line unicorn/no-null
308
373
  let message: Message | undefined | null = null
@@ -322,10 +387,10 @@ describe("reactivity", () => {
322
387
  })
323
388
  })
324
389
 
325
- describe("getAll", () => {
390
+ describe("getAll", async () => {
326
391
  it("should react to `create`", async () => {
327
392
  await createRoot(async () => {
328
- const query = createMessagesQuery(() => [])
393
+ const query = await awaitableCreateMessageQuery(() => [])
329
394
 
330
395
  let messages: Readonly<Message[]> | undefined = undefined
331
396
  await createChangeListener(() => (messages = query.getAll()))
@@ -344,7 +409,9 @@ describe("reactivity", () => {
344
409
 
345
410
  it("should react to `update`", async () => {
346
411
  await createRoot(async () => {
347
- const query = createMessagesQuery(() => [createMessage("1", { en: "before" })])
412
+ const query = await awaitableCreateMessageQuery(() => [
413
+ createMessage("1", { en: "before" }),
414
+ ])
348
415
 
349
416
  let messages: Readonly<Message[]> | undefined = undefined
350
417
  await createChangeListener(() => (messages = query.getAll()))
@@ -369,7 +436,7 @@ describe("reactivity", () => {
369
436
 
370
437
  it("should react to `upsert`", async () => {
371
438
  await createRoot(async () => {
372
- const query = createMessagesQuery(() => [])
439
+ const query = await awaitableCreateMessageQuery(() => [])
373
440
 
374
441
  let messages: Readonly<Message[]> | undefined = undefined
375
442
  await createChangeListener(() => (messages = query.getAll()))
@@ -396,7 +463,7 @@ describe("reactivity", () => {
396
463
 
397
464
  it("should react to `delete`", async () => {
398
465
  await createRoot(async () => {
399
- const query = createMessagesQuery(() => [
466
+ const query = await awaitableCreateMessageQuery(() => [
400
467
  createMessage("1", { en: "" }),
401
468
  createMessage("2", { en: "" }),
402
469
  createMessage("3", { en: "" }),
@@ -421,38 +488,9 @@ describe("reactivity", () => {
421
488
  })
422
489
  })
423
490
 
424
- it("should react to changes to the input `messages`", async () => {
425
- const [inputMessages, setMessages] = createSignal<Message[]>([
426
- createMessage("1", { en: "before" }),
427
- ])
428
- const query = createMessagesQuery(inputMessages)
429
-
430
- let messages: Readonly<Message[]> | undefined = undefined
431
- await createChangeListener(() => (messages = query.getAll()))
432
- expect(Object.values(messages!)).toHaveLength(1)
433
-
434
- query.create({ data: createMessage("2", { en: "" }) })
435
- expect(Object.values(messages!)).toHaveLength(2)
436
- expect(
437
- (
438
- Object.values(messages!)![0]!.variants.find((variant) => variant.languageTag === "en")!
439
- .pattern[0]! as Text
440
- ).value
441
- ).toBe("before")
442
-
443
- setMessages([createMessage("1", { en: "after" })])
444
- expect(Object.values(messages!)).toHaveLength(1)
445
- expect(
446
- (
447
- Object.values(messages!)![0]!.variants.find((variant) => variant.languageTag === "en")!
448
- .pattern[0]! as Text
449
- ).value
450
- ).toBe("after")
451
- })
452
-
453
491
  it("should not mutate messages signal outside the query when using the query", async () => {
454
492
  const [inputMessages] = createSignal<Message[]>([createMessage("1", { en: "before" })])
455
- const query = createMessagesQuery(inputMessages)
493
+ const query = await awaitableCreateMessageQuery(inputMessages)
456
494
 
457
495
  let messages: Readonly<Message[]> | undefined = undefined
458
496
  await createChangeListener(() => (messages = query.getAll()))
@@ -467,8 +505,8 @@ describe("reactivity", () => {
467
505
 
468
506
  it("instances should not share state", async () => {
469
507
  await createRoot(async () => {
470
- const query1 = createMessagesQuery(() => [createMessage("1", { en: "before" })])
471
- const query2 = createMessagesQuery(() => [])
508
+ const query1 = await awaitableCreateMessageQuery(() => [createMessage("1", { en: "before" })])
509
+ const query2 = await awaitableCreateMessageQuery(() => [])
472
510
 
473
511
  // eslint-disable-next-line unicorn/no-null
474
512
  let message1: Message | undefined | null = null