@inlang/sdk 0.6.0 → 0.8.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 (48) hide show
  1. package/dist/adapter/solidAdapter.test.js +5 -5
  2. package/dist/createMessageLintReportsQuery.d.ts.map +1 -1
  3. package/dist/createMessageLintReportsQuery.js +0 -1
  4. package/dist/createMessagesQuery.js +1 -1
  5. package/dist/createMessagesQuery.test.js +9 -0
  6. package/dist/loadProject.js +3 -2
  7. package/dist/loadProject.test.js +10 -10
  8. package/dist/messages/variant.d.ts +4 -4
  9. package/dist/messages/variant.d.ts.map +1 -1
  10. package/dist/messages/variant.js +55 -55
  11. package/dist/messages/variant.test.js +102 -45
  12. package/dist/resolve-modules/plugins/errors.d.ts +1 -1
  13. package/dist/resolve-modules/plugins/errors.d.ts.map +1 -1
  14. package/dist/resolve-modules/plugins/errors.js +1 -1
  15. package/dist/resolve-modules/plugins/resolvePlugins.d.ts.map +1 -1
  16. package/dist/resolve-modules/plugins/resolvePlugins.js +1 -11
  17. package/dist/resolve-modules/plugins/resolvePlugins.test.js +0 -28
  18. package/dist/resolve-modules/plugins/types.d.ts +0 -4
  19. package/dist/resolve-modules/plugins/types.d.ts.map +1 -1
  20. package/dist/test-utilities/createMessage.d.ts +1 -1
  21. package/dist/test-utilities/createMessage.js +1 -1
  22. package/dist/test-utilities/createMessage.test.js +4 -4
  23. package/package.json +1 -1
  24. package/src/adapter/solidAdapter.test.ts +13 -13
  25. package/src/adapter/solidAdapter.ts +1 -1
  26. package/src/api.ts +2 -2
  27. package/src/createMessageLintReportsQuery.ts +4 -5
  28. package/src/createMessagesQuery.test.ts +30 -17
  29. package/src/createMessagesQuery.ts +3 -3
  30. package/src/lint/message/lintMessages.ts +1 -1
  31. package/src/lint/message/lintSingleMessage.test.ts +1 -1
  32. package/src/lint/message/lintSingleMessage.ts +2 -2
  33. package/src/loadProject.test.ts +14 -14
  34. package/src/loadProject.ts +15 -15
  35. package/src/messages/errors.ts +2 -2
  36. package/src/messages/variant.test.ts +113 -49
  37. package/src/messages/variant.ts +73 -67
  38. package/src/parseConfig.ts +2 -2
  39. package/src/resolve-modules/import.test.ts +2 -2
  40. package/src/resolve-modules/import.ts +1 -1
  41. package/src/resolve-modules/message-lint-rules/resolveMessageLintRules.ts +1 -1
  42. package/src/resolve-modules/plugins/errors.ts +2 -2
  43. package/src/resolve-modules/plugins/resolvePlugins.test.ts +2 -33
  44. package/src/resolve-modules/plugins/resolvePlugins.ts +16 -27
  45. package/src/resolve-modules/plugins/types.ts +0 -4
  46. package/src/resolve-modules/resolveModules.ts +4 -4
  47. package/src/test-utilities/createMessage.test.ts +7 -7
  48. package/src/test-utilities/createMessage.ts +1 -1
@@ -32,7 +32,7 @@ const exampleMessages = [
32
32
  variants: [
33
33
  {
34
34
  languageTag: "en",
35
- match: {},
35
+ match: [],
36
36
  pattern: [
37
37
  {
38
38
  type: "Text",
@@ -48,7 +48,7 @@ const exampleMessages = [
48
48
  variants: [
49
49
  {
50
50
  languageTag: "en",
51
- match: {},
51
+ match: [],
52
52
  pattern: [
53
53
  {
54
54
  type: "Text",
@@ -190,7 +190,7 @@ describe("messages", () => {
190
190
  variants: [
191
191
  {
192
192
  languageTag: "en",
193
- match: {},
193
+ match: [],
194
194
  pattern: [
195
195
  {
196
196
  type: "Text",
@@ -254,7 +254,7 @@ describe("lint", () => {
254
254
  where: { id: "a" },
255
255
  data: {
256
256
  ...exampleMessages[0],
257
- variants: [{ languageTag: "en", match: {}, pattern: [{ type: "Text", value: "new" }] }],
257
+ variants: [{ languageTag: "en", match: [], pattern: [{ type: "Text", value: "new" }] }],
258
258
  },
259
259
  });
260
260
  expect(counter).toBe(1);
@@ -264,7 +264,7 @@ describe("lint", () => {
264
264
  where: { id: "a" },
265
265
  data: {
266
266
  ...exampleMessages[0],
267
- variants: [{ languageTag: "en", match: {}, pattern: [{ type: "Text", value: "new" }] }],
267
+ variants: [{ languageTag: "en", match: [], pattern: [{ type: "Text", value: "new" }] }],
268
268
  },
269
269
  });
270
270
  expect(counter).toBe(6);
@@ -1 +1 @@
1
- {"version":3,"file":"createMessageLintReportsQuery.d.ts","sourceRoot":"","sources":["../src/createMessageLintReportsQuery.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,wBAAwB,EAA8B,MAAM,UAAU,CAAA;AACnG,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAA;AAC/D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAA;AAChE,OAAO,KAAK,EAAqB,OAAO,EAAE,MAAM,0BAA0B,CAAA;AAI1E;;GAEG;AACH,wBAAgB,6BAA6B,CAC5C,QAAQ,EAAE,MAAM,KAAK,CAAC,OAAO,CAAC,GAAG,SAAS,EAC1C,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,CAsD9C"}
1
+ {"version":3,"file":"createMessageLintReportsQuery.d.ts","sourceRoot":"","sources":["../src/createMessageLintReportsQuery.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,wBAAwB,EAA8B,MAAM,UAAU,CAAA;AACnG,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAA;AAC/D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAA;AAChE,OAAO,KAAK,EAAqB,OAAO,EAAE,MAAM,0BAA0B,CAAA;AAI1E;;GAEG;AACH,wBAAgB,6BAA6B,CAC5C,QAAQ,EAAE,MAAM,KAAK,CAAC,OAAO,CAAC,GAAG,SAAS,EAC1C,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,CAqD9C"}
@@ -13,7 +13,6 @@ export function createMessageLintReportsQuery(messages, settings, installedMessa
13
13
  const _messages = messages();
14
14
  const _settings = settings();
15
15
  if (_messages && _settings && modules) {
16
- // console.log("new calculation")
17
16
  // index.clear()
18
17
  for (const message of _messages) {
19
18
  // TODO: only lint changed messages and update arrays selectively
@@ -9,7 +9,7 @@ export function createMessagesQuery(messages) {
9
9
  const index = new ReactiveMap();
10
10
  createEffect(() => {
11
11
  index.clear();
12
- for (const message of messages()) {
12
+ for (const message of structuredClone(messages())) {
13
13
  index.set(message.id, message);
14
14
  }
15
15
  });
@@ -276,6 +276,15 @@ describe("reactivity", () => {
276
276
  expect(Object.values(messages)[0].variants.find((variant) => variant.languageTag === "en")
277
277
  .pattern[0].value).toBe("after");
278
278
  });
279
+ it("should not mutate messages signal outside the query when using the query", async () => {
280
+ const [inputMessages] = createSignal([createMessage("1", { en: "before" })]);
281
+ const query = createMessagesQuery(inputMessages);
282
+ let messages = undefined;
283
+ await createChangeListener(() => (messages = query.getAll()));
284
+ expect(Object.values(messages)).toHaveLength(1);
285
+ query.create({ data: createMessage("2", { en: "" }) });
286
+ expect(inputMessages().length).toBe(1);
287
+ });
279
288
  });
280
289
  });
281
290
  it("instances should not share state", async () => {
@@ -25,7 +25,9 @@ export const loadProject = async (args) => {
25
25
  loadSettings({ settingsFilePath: args.settingsFilePath, nodeishFs: args.nodeishFs })
26
26
  .then((settings) => {
27
27
  setSettings(settings);
28
- args._capture?.("SDK used settings", settings);
28
+ // rename settings to get a convenient access to the data in Posthog
29
+ const project_settings = settings;
30
+ args._capture?.("SDK used settings", { project_settings });
29
31
  })
30
32
  .catch((err) => {
31
33
  markInitAsFailed(err);
@@ -56,7 +58,6 @@ export const loadProject = async (args) => {
56
58
  resolveModules({ settings: _settings, nodeishFs: args.nodeishFs, _import: args._import })
57
59
  .then((resolvedModules) => {
58
60
  setResolvedModules(resolvedModules);
59
- // TODO: handle `detectedLanguageTags`
60
61
  })
61
62
  .catch((err) => markInitAsFailed(err));
62
63
  });
@@ -41,7 +41,7 @@ const exampleMessages = [
41
41
  variants: [
42
42
  {
43
43
  languageTag: "en",
44
- match: {},
44
+ match: [],
45
45
  pattern: [
46
46
  {
47
47
  type: "Text",
@@ -57,7 +57,7 @@ const exampleMessages = [
57
57
  variants: [
58
58
  {
59
59
  languageTag: "en",
60
- match: {},
60
+ match: [],
61
61
  pattern: [
62
62
  {
63
63
  type: "Text",
@@ -434,7 +434,7 @@ describe("functionality", () => {
434
434
  variants: [
435
435
  {
436
436
  languageTag: "en",
437
- match: {},
437
+ match: [],
438
438
  pattern: [
439
439
  {
440
440
  type: "Text",
@@ -444,7 +444,7 @@ describe("functionality", () => {
444
444
  },
445
445
  {
446
446
  languageTag: "de",
447
- match: {},
447
+ match: [],
448
448
  pattern: [
449
449
  {
450
450
  type: "Text",
@@ -463,7 +463,7 @@ describe("functionality", () => {
463
463
  variants: [
464
464
  {
465
465
  languageTag: "en",
466
- match: {},
466
+ match: [],
467
467
  pattern: [
468
468
  {
469
469
  type: "Text",
@@ -473,7 +473,7 @@ describe("functionality", () => {
473
473
  },
474
474
  {
475
475
  languageTag: "de",
476
- match: {},
476
+ match: [],
477
477
  pattern: [
478
478
  {
479
479
  type: "Text",
@@ -496,7 +496,7 @@ describe("functionality", () => {
496
496
  variants: [
497
497
  {
498
498
  languageTag: "en",
499
- match: {},
499
+ match: [],
500
500
  pattern: [
501
501
  {
502
502
  type: "Text",
@@ -506,7 +506,7 @@ describe("functionality", () => {
506
506
  },
507
507
  {
508
508
  languageTag: "de",
509
- match: {},
509
+ match: [],
510
510
  pattern: [
511
511
  {
512
512
  type: "Text",
@@ -522,7 +522,7 @@ describe("functionality", () => {
522
522
  variants: [
523
523
  {
524
524
  languageTag: "en",
525
- match: {},
525
+ match: [],
526
526
  pattern: [
527
527
  {
528
528
  type: "Text",
@@ -532,7 +532,7 @@ describe("functionality", () => {
532
532
  },
533
533
  {
534
534
  languageTag: "de",
535
- match: {},
535
+ match: [],
536
536
  pattern: [
537
537
  {
538
538
  type: "Text",
@@ -9,12 +9,12 @@ import { MessagePatternsForLanguageTagDoNotExistError, MessageVariantAlreadyExis
9
9
  * (if it exists).
10
10
  *
11
11
  * @example
12
- * const variant = getVariant(message, { where: { languageTag: "en", selectors: { gender: "male" }}});
12
+ * const variant = getVariant(message, { where: { languageTag: "en", match: ["male"]}});
13
13
  */
14
14
  export declare function getVariant(message: Message, args: {
15
15
  where: {
16
16
  languageTag: LanguageTag;
17
- selectors?: Variant["match"];
17
+ match?: Variant["match"];
18
18
  };
19
19
  }): Variant | undefined;
20
20
  /**
@@ -34,12 +34,12 @@ export declare function createVariant(message: Message, args: {
34
34
  * All actions are immutable.
35
35
  *
36
36
  * @example
37
- * const message = updateVariant(message, { languageTag: "en", selectors: { gender: "male" }, pattern: []})
37
+ * const message = updateVariant(message, { languageTag: "en", match: ["male"], pattern: []})
38
38
  */
39
39
  export declare function updateVariantPattern(message: Message, args: {
40
40
  where: {
41
41
  languageTag: LanguageTag;
42
- selectors: Record<string, string>;
42
+ match: Variant["match"];
43
43
  };
44
44
  data: Variant["pattern"];
45
45
  }): Result<Message, MessageVariantDoesNotExistError | MessagePatternsForLanguageTagDoNotExistError>;
@@ -1 +1 @@
1
- {"version":3,"file":"variant.d.ts","sourceRoot":"","sources":["../../src/messages/variant.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,2BAA2B,CAAA;AAC9E,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAA;AAC5C,OAAO,EACN,4CAA4C,EAC5C,gCAAgC,EAChC,+BAA+B,EAC/B,MAAM,aAAa,CAAA;AAEpB;;;;;;;;;GASG;AACH,wBAAgB,UAAU,CACzB,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE;IACL,KAAK,EAAE;QACN,WAAW,EAAE,WAAW,CAAA;QACxB,SAAS,CAAC,EAAE,OAAO,CAAC,OAAO,CAAC,CAAA;KAC5B,CAAA;CACD,GACC,OAAO,GAAG,SAAS,CASrB;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAC5B,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE;IACL,IAAI,EAAE,OAAO,CAAA;CACb,GACC,MAAM,CAAC,OAAO,EAAE,gCAAgC,CAAC,CAcnD;AAED;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CACnC,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE;IACL,KAAK,EAAE;QACN,WAAW,EAAE,WAAW,CAAA;QACxB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KACjC,CAAA;IACD,IAAI,EAAE,OAAO,CAAC,SAAS,CAAC,CAAA;CACxB,GACC,MAAM,CAAC,OAAO,EAAE,+BAA+B,GAAG,4CAA4C,CAAC,CAqBjG"}
1
+ {"version":3,"file":"variant.d.ts","sourceRoot":"","sources":["../../src/messages/variant.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,2BAA2B,CAAA;AAC9E,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAA;AAC5C,OAAO,EACN,4CAA4C,EAC5C,gCAAgC,EAChC,+BAA+B,EAC/B,MAAM,aAAa,CAAA;AAEpB;;;;;;;;;GASG;AACH,wBAAgB,UAAU,CACzB,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE;IACL,KAAK,EAAE;QACN,WAAW,EAAE,WAAW,CAAA;QACxB,KAAK,CAAC,EAAE,OAAO,CAAC,OAAO,CAAC,CAAA;KACxB,CAAA;CACD,GACC,OAAO,GAAG,SAAS,CASrB;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAC5B,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE;IACL,IAAI,EAAE,OAAO,CAAA;CACb,GACC,MAAM,CAAC,OAAO,EAAE,gCAAgC,CAAC,CAanD;AAED;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CACnC,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE;IACL,KAAK,EAAE;QACN,WAAW,EAAE,WAAW,CAAA;QACxB,KAAK,EAAE,OAAO,CAAC,OAAO,CAAC,CAAA;KACvB,CAAA;IACD,IAAI,EAAE,OAAO,CAAC,SAAS,CAAC,CAAA;CACxB,GACC,MAAM,CAAC,OAAO,EAAE,+BAA+B,GAAG,4CAA4C,CAAC,CAqBjG"}
@@ -7,10 +7,10 @@ import { MessagePatternsForLanguageTagDoNotExistError, MessageVariantAlreadyExis
7
7
  * (if it exists).
8
8
  *
9
9
  * @example
10
- * const variant = getVariant(message, { where: { languageTag: "en", selectors: { gender: "male" }}});
10
+ * const variant = getVariant(message, { where: { languageTag: "en", match: ["male"]}});
11
11
  */
12
12
  export function getVariant(message, args) {
13
- const variant = matchMostSpecificVariant(message, args.where.languageTag, args.where.selectors);
13
+ const variant = matchMostSpecificVariant(message, args.where.languageTag, args.where.match);
14
14
  if (variant) {
15
15
  //! do not return a reference to the message in a resource
16
16
  //! modifications to the returned message will leak into the
@@ -33,10 +33,9 @@ export function createVariant(message, args) {
33
33
  if (matchVariant(copy, args.data.languageTag, args.data.match)) {
34
34
  return { error: new MessageVariantAlreadyExistsError(message.id, args.data.languageTag) };
35
35
  }
36
- // need to resolve selectors to match length and order of message selectors
37
36
  copy.variants.push({
38
37
  ...args.data,
39
- match: resolveSelector(copy.selectors, args.data.match),
38
+ match: args.data.match,
40
39
  });
41
40
  return { data: copy };
42
41
  }
@@ -46,7 +45,7 @@ export function createVariant(message, args) {
46
45
  * All actions are immutable.
47
46
  *
48
47
  * @example
49
- * const message = updateVariant(message, { languageTag: "en", selectors: { gender: "male" }, pattern: []})
48
+ * const message = updateVariant(message, { languageTag: "en", match: ["male"], pattern: []})
50
49
  */
51
50
  export function updateVariantPattern(message, args) {
52
51
  const copy = structuredClone(message);
@@ -56,7 +55,7 @@ export function updateVariantPattern(message, args) {
56
55
  error: new MessagePatternsForLanguageTagDoNotExistError(message.id, args.where.languageTag),
57
56
  };
58
57
  }
59
- const variant = matchVariant(copy, args.where.languageTag, args.where.selectors);
58
+ const variant = matchVariant(copy, args.where.languageTag, args.where.match);
60
59
  if (variant === undefined) {
61
60
  return { error: new MessageVariantDoesNotExistError(message.id, args.where.languageTag) };
62
61
  }
@@ -70,21 +69,24 @@ export function updateVariantPattern(message, args) {
70
69
  * Returns the specific variant defined by selectors or undefined
71
70
  *
72
71
  * @example
73
- * const variant = matchVariant(message, languageTag: "en", selectors: { gender: "male" })
72
+ * const variant = matchVariant(message, languageTag: "en", match: ["male"])
74
73
  */
75
- const matchVariant = (message, languageTag, selectors) => {
76
- // resolve preferenceSelectors to match length and order of message selectors
77
- const resolvedSelectors = resolveSelector(message.selectors, selectors);
74
+ const matchVariant = (message, languageTag, match) => {
78
75
  const languageVariants = message.variants.filter((variant) => variant.languageTag === languageTag);
79
76
  if (languageVariants.length === 0)
80
77
  return undefined;
81
78
  for (const variant of languageVariants) {
82
79
  let isMatch = true;
83
80
  //check if vaiant is a match
84
- for (const [key, value] of Object.entries(variant.match)) {
85
- if (resolvedSelectors[key] !== value) {
86
- isMatch = false;
87
- }
81
+ if (variant.match.length > 0) {
82
+ variant.match.map((value, index) => {
83
+ if (match && match[index] !== value) {
84
+ isMatch = false;
85
+ }
86
+ });
87
+ }
88
+ if (!message.selectors || !match || match.length !== message.selectors.length) {
89
+ isMatch = false;
88
90
  }
89
91
  if (isMatch) {
90
92
  return variant;
@@ -98,47 +100,61 @@ const matchVariant = (message, languageTag, selectors) => {
98
100
  * @example
99
101
  * const variant = matchMostSpecificVariant(message, languageTag: "en", selectors: { gender: "male" })
100
102
  */
101
- const matchMostSpecificVariant = (message, languageTag, selectors) => {
102
- // make selector undefined if empty object
103
- selectors = JSON.stringify(selectors) === "{}" ? undefined : selectors;
103
+ const matchMostSpecificVariant = (message, languageTag, match) => {
104
104
  // resolve preferenceSelectors to match length and order of message selectors
105
- const resolvedSelectors = resolveSelector(message.selectors, selectors);
106
105
  const index = {};
107
106
  for (const variant of message.variants) {
108
107
  if (variant.languageTag !== languageTag)
109
108
  continue;
110
109
  let isMatch = true;
110
+ // if slector and stored match are not the same throw error
111
+ if (variant.match.length !== message.selectors.length) {
112
+ return undefined;
113
+ }
111
114
  //check if variant is a match
112
- for (const [key, value] of Object.entries(variant.match)) {
113
- if (resolvedSelectors[key] !== value && value !== "*") {
114
- isMatch = false;
115
- }
115
+ if (variant.match.length > 0) {
116
+ variant.match.map((value, index) => {
117
+ if (match && match[index] !== value && value !== "*") {
118
+ isMatch = false;
119
+ }
120
+ });
116
121
  }
117
- if (isMatch && selectors) {
118
- // add variant to nested index
122
+ if (isMatch && match && match.length > 0) {
119
123
  // eslint-disable-next-line no-inner-declarations
120
- function recursiveAddToIndex(currentIndex, currentKeys, variant) {
121
- if (currentKeys[0]?.name) {
122
- const key = variant.match[currentKeys[0].name];
123
- if (key) {
124
- if (currentKeys.length === 1) {
125
- currentIndex[key] = variant;
126
- }
127
- else {
128
- if (!currentIndex[key]) {
129
- currentIndex[key] = {};
130
- }
131
- recursiveAddToIndex(currentIndex[key], currentKeys.slice(1), variant);
124
+ function recursiveAddToIndex(currentIndex, selectorIndex, selectorLength, variant) {
125
+ const key = variant.match[selectorIndex];
126
+ if (key) {
127
+ if (selectorIndex === 1) {
128
+ currentIndex[key] = variant;
129
+ }
130
+ else {
131
+ if (!currentIndex[key]) {
132
+ currentIndex[key] = {};
132
133
  }
134
+ recursiveAddToIndex(currentIndex[key], selectorIndex + 1, selectorLength, variant);
133
135
  }
134
136
  }
135
137
  }
136
- recursiveAddToIndex(index, message.selectors, variant);
138
+ recursiveAddToIndex(index, 0, message.selectors ? message.selectors.length - 1 : 0, variant);
137
139
  }
138
- else if (isMatch && !selectors) {
140
+ else if (isMatch && !match) {
139
141
  return variant;
140
142
  }
141
143
  }
144
+ // if number of selectors and numver of required match is not the same match catch all
145
+ if (!message.selectors || !match || match.length !== message.selectors.length) {
146
+ const catchAllMatcher = [];
147
+ const selectorCount = message.selectors.length;
148
+ catchAllMatcher.push("*");
149
+ for (let i = 0; i < selectorCount - 1; i++) {
150
+ catchAllMatcher.push("*");
151
+ }
152
+ return message.variants.find((v) => v.languageTag === languageTag && JSON.stringify(v.match) === JSON.stringify(catchAllMatcher));
153
+ }
154
+ // if selector is empty match empty variant match
155
+ if (message.selectors && message.selectors.length === 0) {
156
+ return message.variants.find((v) => v.languageTag === languageTag && JSON.stringify(v.match) === "[]");
157
+ }
142
158
  //find the most specific variant
143
159
  const findOptimalMatch = (index, selectors) => {
144
160
  const keys = Object.keys(index);
@@ -156,21 +172,5 @@ const matchMostSpecificVariant = (message, languageTag, selectors) => {
156
172
  }
157
173
  return undefined;
158
174
  };
159
- return findOptimalMatch(index, Object.values(resolvedSelectors));
160
- };
161
- /**
162
- * Returns resolved selector.
163
- * -> Adds all possible selectors, if not defined it adds '*'. Order is determined by messageSelectors
164
- *
165
- * @example
166
- * const variant = resolveSelector(["gender","count"], selector: {count: "2"})
167
- */
168
- const resolveSelector = (messageSelectors, selectors) => {
169
- const resolvedSelectors = {};
170
- if (!selectors)
171
- return {};
172
- for (const messageSelector of messageSelectors) {
173
- resolvedSelectors[messageSelector.name] = selectors[messageSelector.name] ?? "*";
174
- }
175
- return resolvedSelectors;
175
+ return findOptimalMatch(index, match || []);
176
176
  };