@inlang/sdk 0.34.8 → 0.34.10

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 (55) hide show
  1. package/dist/adapter/solidAdapter.js +1 -1
  2. package/dist/adapter/solidAdapter.test.js +60 -23
  3. package/dist/api.d.ts +16 -8
  4. package/dist/api.d.ts.map +1 -1
  5. package/dist/createMessageLintReportsQuery.d.ts +5 -1
  6. package/dist/createMessageLintReportsQuery.d.ts.map +1 -1
  7. package/dist/createMessageLintReportsQuery.js +165 -62
  8. package/dist/createMessagesQuery.d.ts.map +1 -1
  9. package/dist/createMessagesQuery.js +30 -12
  10. package/dist/createNewProject.d.ts +0 -5
  11. package/dist/createNewProject.d.ts.map +1 -1
  12. package/dist/createNewProject.js +0 -5
  13. package/dist/lint/message/lintSingleMessage.d.ts.map +1 -1
  14. package/dist/lint/message/lintSingleMessage.js +3 -1
  15. package/dist/loadProject.d.ts.map +1 -1
  16. package/dist/loadProject.js +6 -2
  17. package/dist/loadProject.test.js +38 -25
  18. package/dist/persistence/filelock/acquireFileLock.d.ts.map +1 -1
  19. package/dist/persistence/filelock/acquireFileLock.js +2 -2
  20. package/dist/persistence/filelock/releaseLock.js +1 -1
  21. package/dist/reactivity/solid.d.ts +2 -1
  22. package/dist/reactivity/solid.d.ts.map +1 -1
  23. package/dist/reactivity/solid.js +3 -2
  24. package/dist/reactivity/solid.test.js +38 -1
  25. package/dist/v2/createMessageBundle.d.ts +25 -0
  26. package/dist/v2/createMessageBundle.d.ts.map +1 -0
  27. package/dist/v2/createMessageBundle.js +36 -0
  28. package/dist/v2/createMessageBundle.test.d.ts +2 -0
  29. package/dist/v2/createMessageBundle.test.d.ts.map +1 -0
  30. package/dist/v2/createMessageBundle.test.js +92 -0
  31. package/dist/v2/mocks/plural/bundle.d.ts +3 -0
  32. package/dist/v2/mocks/plural/bundle.d.ts.map +1 -0
  33. package/dist/v2/mocks/plural/bundle.js +140 -0
  34. package/dist/v2/mocks/plural/bundle.test.d.ts +2 -0
  35. package/dist/v2/mocks/plural/bundle.test.d.ts.map +1 -0
  36. package/dist/v2/mocks/plural/bundle.test.js +15 -0
  37. package/package.json +3 -3
  38. package/src/adapter/solidAdapter.test.ts +78 -33
  39. package/src/adapter/solidAdapter.ts +1 -1
  40. package/src/api.ts +15 -8
  41. package/src/createMessageLintReportsQuery.ts +190 -67
  42. package/src/createMessagesQuery.ts +33 -12
  43. package/src/createNewProject.ts +0 -5
  44. package/src/createNodeishFsWithWatcher.ts +1 -1
  45. package/src/lint/message/lintSingleMessage.ts +4 -1
  46. package/src/loadProject.test.ts +45 -24
  47. package/src/loadProject.ts +7 -2
  48. package/src/persistence/filelock/acquireFileLock.ts +4 -2
  49. package/src/persistence/filelock/releaseLock.ts +1 -1
  50. package/src/reactivity/solid.test.ts +54 -1
  51. package/src/reactivity/solid.ts +3 -0
  52. package/src/v2/createMessageBundle.test.ts +95 -0
  53. package/src/v2/createMessageBundle.ts +43 -0
  54. package/src/v2/mocks/plural/bundle.test.ts +18 -0
  55. package/src/v2/mocks/plural/bundle.ts +142 -0
@@ -30,7 +30,7 @@ export const solidAdapter = (project, arg) => {
30
30
  },
31
31
  messageLintReports: {
32
32
  get: project.query.messageLintReports.get,
33
- getAll: project.query.messageLintReports.getAll,
33
+ getAll: convert(project.query.messageLintReports.getAll),
34
34
  },
35
35
  },
36
36
  };
@@ -1,12 +1,9 @@
1
1
  /* eslint-disable @typescript-eslint/no-non-null-assertion */
2
2
  import { describe, it, expect } from "vitest";
3
- import { createResource, createSignal, createEffect, from, createRoot, } from "../reactivity/solid.js";
3
+ import { createEffect, from, createRoot } from "../reactivity/solid.js";
4
4
  import { solidAdapter } from "./solidAdapter.js";
5
5
  import { loadProject } from "../loadProject.js";
6
6
  import { mockRepo } from "@lix-js/client";
7
- function sleep(ms) {
8
- return new Promise((resolve) => setTimeout(resolve, ms));
9
- }
10
7
  // ------------------------------------------------------------------------------------------------
11
8
  const config = {
12
9
  sourceLanguageTag: "en",
@@ -127,8 +124,8 @@ describe("installed", () => {
127
124
  project.setSettings({ ...project.settings(), languageTags: ["en", "fr"] });
128
125
  // TODO: how can we await `setConfig` correctly
129
126
  await new Promise((resolve) => setTimeout(resolve, 0));
130
- expect(counterPlugins).toBe(2); // 2 times because effect creation + set
131
- expect(counterLint).toBe(2); // 2 times because effect creation + set
127
+ expect(counterPlugins).toBe(3); // 3 times because effect creation + setSettings, setResolvedModules
128
+ expect(counterLint).toBe(3); // 3 times because effect creation + setSettings, setResolvedModules
132
129
  });
133
130
  });
134
131
  describe("messages", () => {
@@ -168,7 +165,7 @@ describe("messages", () => {
168
165
  repo,
169
166
  _import: mockImport,
170
167
  }), { from });
171
- let effectOnMessagesCounter = 0;
168
+ let effectOnMessagesCounter = -1;
172
169
  createEffect(() => {
173
170
  project.query.messages.getAll();
174
171
  effectOnMessagesCounter += 1;
@@ -177,7 +174,7 @@ describe("messages", () => {
177
174
  project.setSettings({ ...project.settings(), languageTags: ["en"] });
178
175
  // TODO: how can we await `setConfig` correctly
179
176
  await new Promise((resolve) => setTimeout(resolve, 510));
180
- expect(effectOnMessagesCounter).toBe(7); // 7 = initial effect, setSetting, loadMessage (2x - one per message), setResolvedPlugins, loadMessages (2x - one per message)
177
+ expect(effectOnMessagesCounter).toBe(3); // 3 = setSetting, loadMessage (2x - one per message)
181
178
  expect(Object.values(project.query.messages.getAll()).length).toBe(2);
182
179
  });
183
180
  it("should react to message udpate", async () => {
@@ -268,6 +265,48 @@ describe("messages", () => {
268
265
  });
269
266
  });
270
267
  describe("lint", () => {
268
+ it("should react to changes in config", async () => {
269
+ await createRoot(async () => {
270
+ const repo = await mockRepo();
271
+ const fs = repo.nodeishFs;
272
+ await fs.mkdir("/user/project.inlang", { recursive: true });
273
+ await fs.writeFile("/user/project.inlang/settings.json", JSON.stringify(config));
274
+ const project = solidAdapter(await loadProject({
275
+ projectPath: "/user/project.inlang",
276
+ repo,
277
+ _import: $import,
278
+ }), { from });
279
+ // set counter to -1 since creating effect will execute once
280
+ let counter = -1;
281
+ createEffect(() => {
282
+ project.query.messageLintReports.getAll();
283
+ counter += 1;
284
+ });
285
+ expect(counter).toBe(0);
286
+ // wait for all int reports beeing executed
287
+ await new Promise((resolve) => setTimeout(resolve, 510));
288
+ // 1 because we batch the two lint rules
289
+ expect(counter).toBe(1);
290
+ const currentSettings = project.settings();
291
+ const newConfig = { ...currentSettings, languageTags: ["en", "de"] };
292
+ project.setSettings(newConfig);
293
+ // set settings trigges synchronous -> +1
294
+ expect(counter).toBe(2);
295
+ await new Promise((resolve) => setTimeout(resolve, 510));
296
+ // 4 = 2 + batched(1 (effect->settings) and 1 (effect->Resolved Plugin))
297
+ expect(counter).toBe(3);
298
+ expect(project.query.messageLintReports.getAll()).toEqual([]);
299
+ await new Promise((resolve) => setTimeout(resolve, 510));
300
+ const newConfig2 = { ...project.settings(), languageTags: ["en", "de", "fr"] };
301
+ project.setSettings(newConfig2);
302
+ // set settings trigges synchronous -> +1
303
+ expect(counter).toBe(4);
304
+ await new Promise((resolve) => setTimeout(resolve, 510));
305
+ // 5 -> 4 + 1 new lint report batch
306
+ expect(counter).toBe(5);
307
+ expect(project.query.messageLintReports.getAll()).toEqual([]);
308
+ });
309
+ });
271
310
  it.todo("should react to changes to packages");
272
311
  it.todo("should react to changes to modules");
273
312
  it("should react to changes to messages", async () => {
@@ -281,19 +320,15 @@ describe("lint", () => {
281
320
  repo,
282
321
  _import: $import,
283
322
  }), { from });
284
- const [messages, setMessages] = createSignal();
285
- let counter = 0;
323
+ let counter = -1; // -1 to start counting after the initial effect
286
324
  createEffect(() => {
287
- setMessages(project.query.messages.getAll());
288
- });
289
- const [lintReports] = createResource(messages, async () => {
290
- const reports = await project.query.messageLintReports.getAll();
325
+ project.query.messageLintReports.getAll();
291
326
  counter += 1;
292
- return reports;
293
327
  });
294
- await sleep(10);
328
+ expect(counter).toBe(0);
329
+ await new Promise((resolve) => setTimeout(resolve, 510));
330
+ // 1 -> lint rules are batched - we expect one signal on getAll
295
331
  expect(counter).toBe(1);
296
- expect(lintReports()).toStrictEqual([]);
297
332
  project.query.messages.update({
298
333
  where: { id: "a" },
299
334
  data: {
@@ -301,9 +336,10 @@ describe("lint", () => {
301
336
  variants: [{ languageTag: "en", match: [], pattern: [{ type: "Text", value: "new" }] }],
302
337
  },
303
338
  });
304
- await sleep(10);
305
- expect(counter).toBe(2);
306
- expect(lintReports()).toStrictEqual([]);
339
+ await new Promise((resolve) => setTimeout(resolve, 510));
340
+ // 1 -> previous two messages + 0 - report results are the same - no effect
341
+ expect(counter).toBe(1);
342
+ expect(project.query.messageLintReports.getAll()).toEqual([]);
307
343
  project.query.messages.update({
308
344
  where: { id: "a" },
309
345
  data: {
@@ -311,9 +347,10 @@ describe("lint", () => {
311
347
  variants: [{ languageTag: "en", match: [], pattern: [{ type: "Text", value: "new" }] }],
312
348
  },
313
349
  });
314
- await sleep(10);
315
- expect(counter).toBe(3);
316
- expect(lintReports()).toStrictEqual([]);
350
+ await new Promise((resolve) => setTimeout(resolve, 510));
351
+ // 2 -> the updated message does not update the lint rules - result is the same
352
+ expect(counter).toBe(1);
353
+ expect(project.query.messageLintReports.getAll()).toEqual([]);
317
354
  });
318
355
  });
319
356
  });
package/dist/api.d.ts CHANGED
@@ -48,7 +48,7 @@ export type InlangProject = {
48
48
  };
49
49
  /**
50
50
  * WIP template for async V2 crud interfaces
51
- * E.g. `project.messageBundles.get({ id: "..." })`
51
+ * E.g. `await project.messageBundles.get({ id: "..." })`
52
52
  **/
53
53
  interface Query<T> {
54
54
  get: (args: unknown) => Promise<T>;
@@ -59,9 +59,9 @@ export type Subscribable<Value> = {
59
59
  subscribe: (callback: (value: Value) => void) => void;
60
60
  };
61
61
  export type MessageQueryDelegate = {
62
- onMessageCreate: (messageId: string, message: Message) => void;
63
- onMessageUpdate: (messageId: string, message: Message) => void;
64
- onMessageDelete: (messageId: string) => void;
62
+ onMessageCreate: (messageId: string, message: Message, messages: Message[]) => void;
63
+ onMessageUpdate: (messageId: string, message: Message, messages: Message[]) => void;
64
+ onMessageDelete: (messageId: string, messages: Message[]) => void;
65
65
  onLoaded: (messages: Message[]) => void;
66
66
  onCleanup: () => void;
67
67
  };
@@ -102,15 +102,23 @@ export type MessageQueryApi = {
102
102
  id: Message["id"];
103
103
  };
104
104
  }) => boolean;
105
- setDelegate: (delegate: MessageQueryDelegate) => void;
105
+ setDelegate: (delegate: MessageQueryDelegate | undefined, callOnLoad: boolean) => void;
106
106
  };
107
107
  export type MessageLintReportsQueryApi = {
108
- getAll: () => Promise<MessageLintReport[]>;
109
- get: (args: {
108
+ getAll: Subscribable<MessageLintReport[]> & {
109
+ settled: () => Promise<MessageLintReport[]>;
110
+ };
111
+ get: ((args: {
110
112
  where: {
111
113
  messageId: MessageLintReport["messageId"];
112
114
  };
113
- }) => Promise<Readonly<MessageLintReport[]>>;
115
+ }) => Readonly<MessageLintReport[]>) & {
116
+ subscribe: (args: {
117
+ where: {
118
+ messageId: MessageLintReport["messageId"];
119
+ };
120
+ }, callback: (MessageLintRules: Readonly<MessageLintReport[]>) => void) => void;
121
+ };
114
122
  };
115
123
  export {};
116
124
  //# sourceMappingURL=api.d.ts.map
package/dist/api.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"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"}
@@ -2,7 +2,11 @@ import type { InlangProject, InstalledMessageLintRule, MessageQueryApi } from ".
2
2
  import type { ProjectSettings } from "@inlang/project-settings";
3
3
  import type { resolveModules } from "./resolve-modules/index.js";
4
4
  /**
5
- * Creates a ~~reactive~~ query API for lint reports.
5
+ * Creates a non-reactive async query API for lint reports.
6
+ * e.g. used in editor/.../Listheader.tsx
7
+ *
8
+ * TODO MESDK-50: reactivity should be restored in future
9
+ * See https://github.com/opral/monorepo/pull/2378 for why this design.
6
10
  */
7
11
  export declare function createMessageLintReportsQuery(messagesQuery: MessageQueryApi, settings: () => ProjectSettings, installedMessageLintRules: () => Array<InstalledMessageLintRule>, resolvedModules: () => Awaited<ReturnType<typeof resolveModules>> | undefined): InlangProject["query"]["messageLintReports"];
8
12
  //# sourceMappingURL=createMessageLintReportsQuery.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"createMessageLintReportsQuery.d.ts","sourceRoot":"","sources":["../src/createMessageLintReportsQuery.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,aAAa,EACb,wBAAwB,EAExB,eAAe,EAEf,MAAM,UAAU,CAAA;AACjB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAA;AAC/D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAA;AAQhE;;GAEG;AACH,wBAAgB,6BAA6B,CAC5C,aAAa,EAAE,eAAe,EAC9B,QAAQ,EAAE,MAAM,eAAe,EAC/B,yBAAyB,EAAE,MAAM,KAAK,CAAC,wBAAwB,CAAC,EAChE,eAAe,EAAE,MAAM,OAAO,CAAC,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC,GAAG,SAAS,GAC3E,aAAa,CAAC,OAAO,CAAC,CAAC,oBAAoB,CAAC,CA6E9C"}
1
+ {"version":3,"file":"createMessageLintReportsQuery.d.ts","sourceRoot":"","sources":["../src/createMessageLintReportsQuery.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,aAAa,EACb,wBAAwB,EAExB,eAAe,EAEf,MAAM,UAAU,CAAA;AACjB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAA;AAC/D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAA;AAWhE;;;;;;GAMG;AACH,wBAAgB,6BAA6B,CAC5C,aAAa,EAAE,eAAe,EAC9B,QAAQ,EAAE,MAAM,eAAe,EAC/B,yBAAyB,EAAE,MAAM,KAAK,CAAC,wBAAwB,CAAC,EAChE,eAAe,EAAE,MAAM,OAAO,CAAC,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC,GAAG,SAAS,GAC3E,aAAa,CAAC,OAAO,CAAC,CAAC,oBAAoB,CAAC,CAoJ9C"}
@@ -1,73 +1,176 @@
1
1
  import { lintSingleMessage } from "./lint/index.js";
2
- function sleep(ms) {
3
- return new Promise((resolve) => setTimeout(resolve, ms));
4
- }
2
+ import { ReactiveMap } from "./reactivity/map.js";
3
+ import { createMemo, onCleanup, untrack, batch } from "./reactivity/solid.js";
4
+ import { createSubscribable } from "./loadProject.js";
5
+ import _debug from "debug";
6
+ const debug = _debug("sdk:lintReports");
5
7
  /**
6
- * Creates a ~~reactive~~ query API for lint reports.
8
+ * Creates a non-reactive async query API for lint reports.
9
+ * e.g. used in editor/.../Listheader.tsx
10
+ *
11
+ * TODO MESDK-50: reactivity should be restored in future
12
+ * See https://github.com/opral/monorepo/pull/2378 for why this design.
7
13
  */
8
14
  export function createMessageLintReportsQuery(messagesQuery, settings, installedMessageLintRules, resolvedModules) {
9
- const index = new Map();
10
- const modules = resolvedModules();
11
- const rulesArray = modules?.messageLintRules;
12
- const messageLintRuleLevels = Object.fromEntries(installedMessageLintRules().map((rule) => [rule.id, rule.level]));
13
- const settingsObject = () => {
14
- return {
15
- ...settings(),
16
- messageLintRuleLevels,
17
- };
18
- };
19
- const lintMessage = (message, messages) => {
20
- if (!rulesArray) {
15
+ // @ts-expect-error Reactive map seems to have a problem with Type aliases here
16
+ const index = new ReactiveMap();
17
+ debug("resetting settledReports");
18
+ let settledReports = Promise.resolve();
19
+ let currentBatchEnd = undefined;
20
+ const updatedReports = {};
21
+ // triggered whenever settings or resolved modules changes
22
+ createMemo(() => {
23
+ // we clear the index independent from the change for
24
+ index.clear();
25
+ onCleanup(() => {
26
+ messagesQuery.setDelegate(undefined, false);
27
+ });
28
+ // settings is a signal - effect will be called whenever settings changes
29
+ const _settings = settings();
30
+ if (!_settings)
21
31
  return;
22
- }
23
- // TODO unhandled promise rejection (as before the refactor) but won't tackle this in this pr
24
- lintSingleMessage({
25
- rules: rulesArray,
26
- settings: settingsObject(),
27
- messages: messages,
28
- message: message,
29
- }).then((report) => {
30
- if (report.errors.length === 0 && index.get(message.id) !== report.data) {
31
- // console.log("lintSingleMessage", messageId, report.data.length)
32
- index.set(message.id, report.data);
33
- }
32
+ const _resolvedModules = resolvedModules();
33
+ if (!_resolvedModules)
34
+ return;
35
+ // resolvedModules is a signal - effect will be called whenever resolvedModules changes
36
+ const rulesArray = _resolvedModules.messageLintRules;
37
+ const messageLintRuleLevels = Object.fromEntries(installedMessageLintRules().map((rule) => [rule.id, rule.level]));
38
+ const settingsObject = () => {
39
+ return {
40
+ ...settings(),
41
+ messageLintRuleLevels,
42
+ };
43
+ };
44
+ const sheduleLintMessage = (message, messages) => {
45
+ debug("shedule Lint for message:", message.id);
46
+ const updateOutstandingReportsOnLast = async () => {
47
+ if (currentBatchEnd !== updateOutstandingReportsOnLast) {
48
+ debug("skip triggering reactivy", message.id);
49
+ return;
50
+ }
51
+ debug("finished queue - trigger reactivity", message.id);
52
+ batch(() => {
53
+ for (const [id, reports] of Object.entries(updatedReports)) {
54
+ const currentReports = index.get(id);
55
+ // we only update the report if it differs from the known one - to not trigger reactivity
56
+ if (!reportsEqual(currentReports, reports)) {
57
+ debug("lint reports for message: ", id, " now n:", reports.length);
58
+ index.set(id, reports);
59
+ }
60
+ }
61
+ });
62
+ };
63
+ currentBatchEnd = updateOutstandingReportsOnLast;
64
+ const scheduledLint = lintSingleMessage({
65
+ rules: rulesArray,
66
+ settings: settingsObject(),
67
+ messages: messages,
68
+ message: message,
69
+ }).then((reportsResult) => {
70
+ if (reportsResult.errors.length === 0) {
71
+ debug("lint reports for message: ", message.id, "n:", reportsResult.data.length);
72
+ updatedReports[message.id] = reportsResult.data;
73
+ }
74
+ return updateOutstandingReportsOnLast();
75
+ });
76
+ settledReports = settledReports.then(() => scheduledLint);
77
+ };
78
+ // setup delegate of message query
79
+ const messageQueryChangeDelegate = {
80
+ onCleanup: () => {
81
+ // NOTE: we could cancel all running lint rules - but results get overritten anyway
82
+ index.clear();
83
+ },
84
+ onLoaded: (messages) => {
85
+ // for (const message of messages) {
86
+ // lintMessage(message, messages)
87
+ // }
88
+ debug("sheduluing Lint for all messages - on load");
89
+ batch(() => {
90
+ debug("sheduluing Lint for all messages - subsquencial call?");
91
+ for (const message of messages) {
92
+ // NOTE: this potentually creates thousands of promisses we could create a promise that batches linting
93
+ // NOTE: this produces a lot of signals - we could batch the
94
+ sheduleLintMessage(message, messages);
95
+ }
96
+ });
97
+ },
98
+ onMessageCreate: (messageId, message, messages) => {
99
+ // NOTE: unhandled promise rejection (as before the refactor) but won't tackle this in this pr
100
+ // TODO MESDK-105 reevaluate all lint's instead of those for the messsage that where created
101
+ debug("shedule Lint for message - onMessageCreate", message.id);
102
+ sheduleLintMessage(message, messages);
103
+ },
104
+ onMessageUpdate: (messageId, message, messages) => {
105
+ // NOTE: unhandled promise rejection (as before the refactor) but won't tackle this in this pr
106
+ // TODO MESDK-105 reevaluate all lint's instead of those for the messsage that changed
107
+ debug("shedule Lint for message - onMessageUpdate", message.id);
108
+ sheduleLintMessage(message, messages);
109
+ },
110
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars -- TODO MESDK-105 we gonna need the mesage Property for evaluation
111
+ onMessageDelete: (messageId, _messages) => {
112
+ index.delete(messageId);
113
+ },
114
+ };
115
+ untrack(() => {
116
+ messagesQuery.setDelegate(messageQueryChangeDelegate, true);
34
117
  });
118
+ });
119
+ const get = (args) => {
120
+ debug("get", args.where.messageId);
121
+ return structuredClone(index.get(args.where.messageId));
35
122
  };
36
- const messages = messagesQuery.getAll();
37
- // load report for all messages once
38
- for (const message of messages) {
39
- // NOTE: this potentually creates thousands of promisses we could create a promise that batches linting
40
- lintMessage(message, messages);
41
- }
42
- const messageQueryChangeDelegate = {
43
- onCleanup: () => {
44
- // NOTE: we could cancel all running lint rules - but results get overritten anyway
45
- index.clear();
46
- },
47
- onLoaded: (messages) => {
48
- for (const message of messages) {
49
- lintMessage(message, messages);
50
- }
51
- },
52
- onMessageCreate: (messageId, message) => {
53
- lintMessage(message, messages);
54
- },
55
- onMessageUpdate: (messageId, message) => {
56
- lintMessage(message, messages);
57
- },
58
- onMessageDelete: (messageId) => {
59
- index.delete(messageId);
60
- },
123
+ const getAll = () => {
124
+ const flatValues = [...index.values()].flat();
125
+ debug("getAll", flatValues.length);
126
+ return structuredClone(flatValues.length === 0 ? [] : flatValues);
61
127
  };
62
- messagesQuery.setDelegate(messageQueryChangeDelegate);
63
128
  return {
64
- getAll: async () => {
65
- await sleep(0); // evaluate on next tick to allow for out-of-order effects
66
- return structuredClone([...index.values()].flat().length === 0 ? [] : [...index.values()].flat());
67
- },
68
- get: async (args) => {
69
- await sleep(0); // evaluate on next tick to allow for out-of-order effects
70
- return structuredClone(index.get(args.where.messageId) ?? []);
71
- },
129
+ getAll: Object.assign(createSubscribable(getAll), {
130
+ settled: async () => {
131
+ await settledReports;
132
+ return getAll();
133
+ },
134
+ }),
135
+ get: Object.assign(get, {
136
+ subscribe: (args, callback) => createSubscribable(() => get(args)).subscribe(callback),
137
+ }),
72
138
  };
73
139
  }
140
+ function reportsEqual(reportsA, reportsB) {
141
+ if (reportsA === undefined && reportsB === undefined) {
142
+ return true;
143
+ }
144
+ else if (reportsA === undefined || reportsB === undefined) {
145
+ return false;
146
+ }
147
+ if (reportsA.length !== reportsB.length) {
148
+ return false;
149
+ }
150
+ for (const [i, element] of reportsA.entries()) {
151
+ if (element?.languageTag !== reportsB[i]?.languageTag) {
152
+ return false;
153
+ }
154
+ if (element?.level !== reportsB[i]?.level) {
155
+ return false;
156
+ }
157
+ if (element?.ruleId !== reportsB[i]?.ruleId) {
158
+ return false;
159
+ }
160
+ if (typeof element?.body !== typeof reportsB[i]?.body) {
161
+ return false;
162
+ }
163
+ if (typeof element?.body === "string") {
164
+ if (reportsB[i]?.body !== reportsB[i]?.body) {
165
+ return false;
166
+ }
167
+ }
168
+ else {
169
+ // NOTE: this was the fastest way to check if both bodies are equal - we can optimize that later if needed
170
+ if (JSON.stringify(element?.body) !== JSON.stringify(element?.body)) {
171
+ return false;
172
+ }
173
+ }
174
+ }
175
+ return true;
176
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"createMessagesQuery.d.ts","sourceRoot":"","sources":["../src/createMessagesQuery.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,aAAa,EAAyC,MAAM,UAAU,CAAA;AAEpF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qCAAqC,CAAA;AAEzE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AAKnD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAA;AA4B/D,KAAK,6BAA6B,GAAG;IACpC,WAAW,EAAE,MAAM,CAAA;IACnB,SAAS,EAAE,iBAAiB,CAAA;IAC5B,QAAQ,EAAE,MAAM,eAAe,GAAG,SAAS,CAAA;IAC3C,eAAe,EAAE,MAAM,OAAO,CAAC,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC,GAAG,SAAS,CAAA;IAC7E,0BAA0B,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,KAAK,IAAI,CAAA;IAC/C,mBAAmB,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,KAAK,IAAI,CAAA;IACxC,mBAAmB,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,KAAK,IAAI,CAAA;CACxC,CAAA;AACD;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,EACnC,WAAW,EACX,SAAS,EACT,QAAQ,EACR,eAAe,EACf,0BAA0B,EAC1B,mBAAmB,EACnB,mBAAmB,GACnB,EAAE,6BAA6B,GAAG,aAAa,CAAC,OAAO,CAAC,CAAC,UAAU,CAAC,CA6MpE"}
1
+ {"version":3,"file":"createMessagesQuery.d.ts","sourceRoot":"","sources":["../src/createMessagesQuery.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,aAAa,EAAyC,MAAM,UAAU,CAAA;AAEpF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qCAAqC,CAAA;AAEzE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AAInD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAA;AA4B/D,KAAK,6BAA6B,GAAG;IACpC,WAAW,EAAE,MAAM,CAAA;IACnB,SAAS,EAAE,iBAAiB,CAAA;IAC5B,QAAQ,EAAE,MAAM,eAAe,GAAG,SAAS,CAAA;IAC3C,eAAe,EAAE,MAAM,OAAO,CAAC,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC,GAAG,SAAS,CAAA;IAC7E,0BAA0B,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,KAAK,IAAI,CAAA;IAC/C,mBAAmB,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,KAAK,IAAI,CAAA;IACxC,mBAAmB,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,KAAK,IAAI,CAAA;CACxC,CAAA;AACD;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,EACnC,WAAW,EACX,SAAS,EACT,QAAQ,EACR,eAAe,EACf,0BAA0B,EAC1B,mBAAmB,EACnB,mBAAmB,GACnB,EAAE,6BAA6B,GAAG,aAAa,CAAC,OAAO,CAAC,CAAC,UAAU,CAAC,CAmNpE"}
@@ -1,15 +1,14 @@
1
1
  import { ReactiveMap } from "./reactivity/map.js";
2
- import { createEffect } from "./reactivity/solid.js";
2
+ import { createEffect, onCleanup } from "./reactivity/solid.js";
3
3
  import { createSubscribable } from "./loadProject.js";
4
4
  import { createNodeishFsWithWatcher } from "./createNodeishFsWithWatcher.js";
5
- import { onCleanup } from "solid-js";
6
5
  import { stringifyMessage } from "./storage/helper.js";
7
6
  import { acquireFileLock } from "./persistence/filelock/acquireFileLock.js";
8
7
  import _debug from "debug";
9
8
  import { releaseLock } from "./persistence/filelock/releaseLock.js";
10
9
  import { PluginLoadMessagesError, PluginSaveMessagesError } from "./errors.js";
11
10
  import { humanIdHash } from "./storage/human-id/human-readable-id.js";
12
- const debug = _debug("sdk:createMessagesQuery");
11
+ const debug = _debug("sdk:messages");
13
12
  function sleep(ms) {
14
13
  return new Promise((resolve) => setTimeout(resolve, ms));
15
14
  }
@@ -19,11 +18,15 @@ function sleep(ms) {
19
18
  export function createMessagesQuery({ projectPath, nodeishFs, settings, resolvedModules, onInitialMessageLoadResult, onLoadMessageResult, onSaveMessageResult, }) {
20
19
  // @ts-expect-error
21
20
  const index = new ReactiveMap();
21
+ let loaded = false;
22
22
  // filepath for the lock folder
23
23
  const messageLockDirPath = projectPath + "/messagelock";
24
24
  let delegate = undefined;
25
- const setDelegate = (newDelegate) => {
25
+ const setDelegate = (newDelegate, onLoad) => {
26
26
  delegate = newDelegate;
27
+ if (newDelegate && loaded && onLoad) {
28
+ newDelegate.onLoaded([...index.values()]);
29
+ }
27
30
  };
28
31
  // Map default alias to message
29
32
  // Assumes that aliases are only created and deleted, not updated
@@ -45,6 +48,7 @@ export function createMessagesQuery({ projectPath, nodeishFs, settings, resolved
45
48
  // we clear the index independent from the change for
46
49
  index.clear();
47
50
  defaultAliasIndex.clear();
51
+ loaded = false;
48
52
  // Load messages -> use settings to subscribe to signals from the settings
49
53
  const _settings = settings();
50
54
  if (!_settings)
@@ -79,7 +83,7 @@ export function createMessagesQuery({ projectPath, nodeishFs, settings, resolved
79
83
  onInitialMessageLoadResult(new Error("no loadMessages in resolved Modules found"));
80
84
  return;
81
85
  }
82
- loadMessagesViaPlugin(fsWithWatcher, messageLockDirPath, messageStates, index, delegate, _settings, // NOTE we bang here - we don't expect the settings to become null during the livetime of a project
86
+ loadMessagesViaPlugin(fsWithWatcher, messageLockDirPath, messageStates, index, undefined /* delegate - we don't pass it here since we will call onLoaded instead */, _settings, // NOTE we bang here - we don't expect the settings to become null during the livetime of a project
83
87
  resolvedPluginApi)
84
88
  .catch((e) => {
85
89
  // propagate initial load error to calling laodProject function
@@ -88,6 +92,7 @@ export function createMessagesQuery({ projectPath, nodeishFs, settings, resolved
88
92
  .then(() => {
89
93
  onInitialMessageLoadResult();
90
94
  delegate?.onLoaded([...index.values()]);
95
+ loaded = true;
91
96
  });
92
97
  });
93
98
  const get = (args) => index.get(args.where.id);
@@ -124,7 +129,7 @@ export function createMessagesQuery({ projectPath, nodeishFs, settings, resolved
124
129
  defaultAliasIndex.set(data.alias.default, data);
125
130
  }
126
131
  messageStates.messageDirtyFlags[data.id] = true;
127
- delegate?.onMessageCreate(data.id, index.get(data.id));
132
+ delegate?.onMessageCreate(data.id, index.get(data.id), [...index.values()]);
128
133
  scheduleSave();
129
134
  return true;
130
135
  },
@@ -146,7 +151,7 @@ export function createMessagesQuery({ projectPath, nodeishFs, settings, resolved
146
151
  return false;
147
152
  index.set(where.id, { ...message, ...data });
148
153
  messageStates.messageDirtyFlags[where.id] = true;
149
- delegate?.onMessageCreate(where.id, index.get(data.id));
154
+ delegate?.onMessageUpdate(where.id, index.get(data.id), [...index.values()]);
150
155
  scheduleSave();
151
156
  return true;
152
157
  },
@@ -158,12 +163,12 @@ export function createMessagesQuery({ projectPath, nodeishFs, settings, resolved
158
163
  defaultAliasIndex.set(data.alias.default, data);
159
164
  }
160
165
  messageStates.messageDirtyFlags[where.id] = true;
161
- delegate?.onMessageCreate(data.id, index.get(data.id));
166
+ delegate?.onMessageCreate(data.id, index.get(data.id), [...index.values()]);
162
167
  }
163
168
  else {
164
169
  index.set(where.id, { ...message, ...data });
165
170
  messageStates.messageDirtyFlags[where.id] = true;
166
- delegate?.onMessageUpdate(data.id, index.get(data.id));
171
+ delegate?.onMessageUpdate(data.id, index.get(data.id), [...index.values()]);
167
172
  }
168
173
  scheduleSave();
169
174
  return true;
@@ -177,7 +182,7 @@ export function createMessagesQuery({ projectPath, nodeishFs, settings, resolved
177
182
  }
178
183
  index.delete(where.id);
179
184
  messageStates.messageDirtyFlags[where.id] = true;
180
- delegate?.onMessageDelete(where.id);
185
+ delegate?.onMessageDelete(where.id, [...index.values()]);
181
186
  scheduleSave();
182
187
  return true;
183
188
  },
@@ -223,6 +228,7 @@ async function loadMessagesViaPlugin(fs, lockDirPath, messageState, messages, de
223
228
  nodeishFs: fs,
224
229
  }));
225
230
  let loadedMessageCount = 0;
231
+ const deletedMessages = new Set(messages.keys());
226
232
  for (const loadedMessage of loadedMessages) {
227
233
  const loadedMessageClone = structuredClone(loadedMessage);
228
234
  const currentMessages = [...messages.values()]
@@ -234,6 +240,8 @@ async function loadMessagesViaPlugin(fs, lockDirPath, messageState, messages, de
234
240
  throw new Error("more than one message with the same id or alias found ");
235
241
  }
236
242
  else if (currentMessages.length === 1) {
243
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- length has checked beforhand
244
+ deletedMessages.delete(currentMessages[0].id);
237
245
  // update message in place - leave message id and alias untouched
238
246
  loadedMessageClone.alias = {};
239
247
  // TODO #1585 we have to map the id of the importedMessage to the alias and fill the id property with the id of the existing message - change when import mesage provides importedMessage.alias
@@ -256,7 +264,7 @@ async function loadMessagesViaPlugin(fs, lockDirPath, messageState, messages, de
256
264
  messages.set(loadedMessageClone.id, loadedMessageClone);
257
265
  // NOTE could use hash instead of the whole object JSON to save memory...
258
266
  messageState.messageLoadHash[loadedMessageClone.id] = importedEnecoded;
259
- delegate?.onMessageUpdate(loadedMessageClone.id, loadedMessageClone);
267
+ delegate?.onMessageUpdate(loadedMessageClone.id, loadedMessageClone, [...messages.values()]);
260
268
  loadedMessageCount++;
261
269
  }
262
270
  else {
@@ -281,7 +289,7 @@ async function loadMessagesViaPlugin(fs, lockDirPath, messageState, messages, de
281
289
  // we don't have to check - done before hand if (messages.has(loadedMessageClone.id)) return false
282
290
  messages.set(loadedMessageClone.id, loadedMessageClone);
283
291
  messageState.messageLoadHash[loadedMessageClone.id] = importedEnecoded;
284
- delegate?.onMessageUpdate(loadedMessageClone.id, loadedMessageClone);
292
+ delegate?.onMessageUpdate(loadedMessageClone.id, loadedMessageClone, [...messages.values()]);
285
293
  loadedMessageCount++;
286
294
  }
287
295
  if (loadedMessageCount > maxMessagesPerTick) {
@@ -292,6 +300,16 @@ async function loadMessagesViaPlugin(fs, lockDirPath, messageState, messages, de
292
300
  loadedMessageCount = 0;
293
301
  }
294
302
  }
303
+ loadedMessageCount = 0;
304
+ for (const deletedMessageId of deletedMessages) {
305
+ messages.delete(deletedMessageId);
306
+ delegate?.onMessageDelete(deletedMessageId, [...messages.values()]);
307
+ loadedMessageCount++;
308
+ if (loadedMessageCount > maxMessagesPerTick) {
309
+ await sleep(0);
310
+ loadedMessageCount = 0;
311
+ }
312
+ }
295
313
  await releaseLock(fs, lockDirPath, "loadMessage", lockTime);
296
314
  lockTime = undefined;
297
315
  debug("loadMessagesViaPlugin: " + loadedMessages.length + " Messages processed ");