@saykit/config 0.0.0-beta-20260729112211 → 0.0.0-beta-20260729131250

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.
@@ -25,28 +25,28 @@ function assignSequenceIdentifiers(message, sequence = { current: 0 }, equivalen
25
25
  * Collect the identifiers already assigned before this pass runs, so generated
26
26
  * sequence numbers never shadow an explicit one (e.g. an element tagged `0`).
27
27
  *
28
- * Elements that differ need their own tag: they each compile to their own prop,
29
- * and a translator has to be able to tell them apart. Repeats are fine when
30
- * nothing distinguishes them — two identical elements are one prop, the same
31
- * way the same variable interpolated twice is one value — so arguments are
32
- * never checked and elements only when they are not equivalent.
28
+ * A name is claimed by what produced it, not by the name alone. Two that differ
29
+ * each compile to their own prop, and a translator moving them around a sentence
30
+ * has to be able to tell them apart, so they are a build error. Repeats are fine
31
+ * when nothing distinguishes them: the same variable interpolated twice is one
32
+ * value, and two identical elements are one tag.
33
33
  */
34
34
  function collectAssignedIdentifiers(message, equivalent) {
35
35
  const tags = /* @__PURE__ */ new Map();
36
- const values = /* @__PURE__ */ new Set();
36
+ const values = /* @__PURE__ */ new Map();
37
+ function claim(claimed, identifier, expression, conflict) {
38
+ if (claimed.has(identifier) && !equivalent(claimed.get(identifier), expression)) throw new Error(conflict);
39
+ claimed.set(identifier, expression);
40
+ }
37
41
  function walk(message) {
38
- if (message instanceof ElementMessage && typeof message.identifier === "string") {
39
- const previous = tags.get(message.identifier);
40
- if (previous && !equivalent(previous.expression, message.expression)) throw new Error(`Duplicate element tag '${message.identifier}', give each element in a message its own tag unless they are identical`);
41
- tags.set(message.identifier, message);
42
- }
43
- if ((message instanceof ArgumentMessage || message instanceof ChoiceMessage) && typeof message.identifier === "string") values.add(message.identifier);
42
+ if (message instanceof ElementMessage && typeof message.identifier === "string") claim(tags, message.identifier, message.expression, `Duplicate element tag '${message.identifier}', give each element in a message its own tag unless they are identical`);
43
+ if ((message instanceof ArgumentMessage || message instanceof ChoiceMessage) && typeof message.identifier === "string") claim(values, message.identifier, message.expression, `Duplicate placeholder name '${message.identifier}', give each value in a message its own name unless they are identical`);
44
44
  if (message instanceof CompositeMessage || message instanceof ElementMessage) for (const child of message.children) walk(child);
45
45
  if (message instanceof ChoiceMessage) for (const branch of message.branches) walk(branch.value);
46
46
  }
47
47
  walk(message);
48
48
  for (const tag of tags.keys()) if (values.has(tag)) throw new Error(`Element tag '${tag}' collides with an argument of the same name`);
49
- return /* @__PURE__ */ new Set([...tags.keys(), ...values]);
49
+ return /* @__PURE__ */ new Set([...tags.keys(), ...values.keys()]);
50
50
  }
51
51
  //#endregion
52
52
  //#region src/features/messages/types.ts
@@ -1,14 +1,14 @@
1
1
  //#region src/features/messages/identifier.d.ts
2
2
  declare const AUTO_INCREMENT_IDENTIFIER: unique symbol;
3
3
  /**
4
- * Decides whether two elements sharing a tag are the same element, and so may
5
- * share it. Only the syntax that produced them can answer that, so the caller
6
- * supplies the comparison; by default no two elements are interchangeable.
4
+ * Decides whether two placeholders sharing a name are the same placeholder, and
5
+ * so may share it. Only the syntax that produced them can answer that, so the
6
+ * caller supplies the comparison; by default nothing is interchangeable.
7
7
  */
8
- type ElementEquivalence = (a: any, b: any) => boolean;
8
+ type PlaceholderEquivalence = (a: any, b: any) => boolean;
9
9
  declare function assignSequenceIdentifiers(message: Message, sequence?: {
10
10
  current: number;
11
- }, equivalent?: ElementEquivalence): void;
11
+ }, equivalent?: PlaceholderEquivalence): void;
12
12
  //#endregion
13
13
  //#region src/features/messages/types.d.ts
14
14
  declare abstract class Base {
@@ -66,4 +66,4 @@ declare function convertMessageToIcu(message: Message): string;
66
66
  //#region src/features/messages/hash.d.ts
67
67
  declare function generateHash(input: string, context?: string): string;
68
68
  //#endregion
69
- export { AUTO_INCREMENT_IDENTIFIER, ArgumentMessage, ChoiceMessage, CompositeMessage, ElementEquivalence, ElementMessage, LiteralMessage, Message, assignSequenceIdentifiers, convertMessageToIcu, generateHash };
69
+ export { AUTO_INCREMENT_IDENTIFIER, ArgumentMessage, ChoiceMessage, CompositeMessage, ElementMessage, LiteralMessage, Message, PlaceholderEquivalence, assignSequenceIdentifiers, convertMessageToIcu, generateHash };
@@ -1,14 +1,14 @@
1
1
  //#region src/features/messages/identifier.d.ts
2
2
  declare const AUTO_INCREMENT_IDENTIFIER: unique symbol;
3
3
  /**
4
- * Decides whether two elements sharing a tag are the same element, and so may
5
- * share it. Only the syntax that produced them can answer that, so the caller
6
- * supplies the comparison; by default no two elements are interchangeable.
4
+ * Decides whether two placeholders sharing a name are the same placeholder, and
5
+ * so may share it. Only the syntax that produced them can answer that, so the
6
+ * caller supplies the comparison; by default nothing is interchangeable.
7
7
  */
8
- type ElementEquivalence = (a: any, b: any) => boolean;
8
+ type PlaceholderEquivalence = (a: any, b: any) => boolean;
9
9
  declare function assignSequenceIdentifiers(message: Message, sequence?: {
10
10
  current: number;
11
- }, equivalent?: ElementEquivalence): void;
11
+ }, equivalent?: PlaceholderEquivalence): void;
12
12
  //#endregion
13
13
  //#region src/features/messages/types.d.ts
14
14
  declare abstract class Base {
@@ -66,4 +66,4 @@ declare function convertMessageToIcu(message: Message): string;
66
66
  //#region src/features/messages/hash.d.ts
67
67
  declare function generateHash(input: string, context?: string): string;
68
68
  //#endregion
69
- export { AUTO_INCREMENT_IDENTIFIER, ArgumentMessage, ChoiceMessage, CompositeMessage, ElementEquivalence, ElementMessage, LiteralMessage, Message, assignSequenceIdentifiers, convertMessageToIcu, generateHash };
69
+ export { AUTO_INCREMENT_IDENTIFIER, ArgumentMessage, ChoiceMessage, CompositeMessage, ElementMessage, LiteralMessage, Message, PlaceholderEquivalence, assignSequenceIdentifiers, convertMessageToIcu, generateHash };
@@ -24,28 +24,28 @@ function assignSequenceIdentifiers(message, sequence = { current: 0 }, equivalen
24
24
  * Collect the identifiers already assigned before this pass runs, so generated
25
25
  * sequence numbers never shadow an explicit one (e.g. an element tagged `0`).
26
26
  *
27
- * Elements that differ need their own tag: they each compile to their own prop,
28
- * and a translator has to be able to tell them apart. Repeats are fine when
29
- * nothing distinguishes them — two identical elements are one prop, the same
30
- * way the same variable interpolated twice is one value — so arguments are
31
- * never checked and elements only when they are not equivalent.
27
+ * A name is claimed by what produced it, not by the name alone. Two that differ
28
+ * each compile to their own prop, and a translator moving them around a sentence
29
+ * has to be able to tell them apart, so they are a build error. Repeats are fine
30
+ * when nothing distinguishes them: the same variable interpolated twice is one
31
+ * value, and two identical elements are one tag.
32
32
  */
33
33
  function collectAssignedIdentifiers(message, equivalent) {
34
34
  const tags = /* @__PURE__ */ new Map();
35
- const values = /* @__PURE__ */ new Set();
35
+ const values = /* @__PURE__ */ new Map();
36
+ function claim(claimed, identifier, expression, conflict) {
37
+ if (claimed.has(identifier) && !equivalent(claimed.get(identifier), expression)) throw new Error(conflict);
38
+ claimed.set(identifier, expression);
39
+ }
36
40
  function walk(message) {
37
- if (message instanceof ElementMessage && typeof message.identifier === "string") {
38
- const previous = tags.get(message.identifier);
39
- if (previous && !equivalent(previous.expression, message.expression)) throw new Error(`Duplicate element tag '${message.identifier}', give each element in a message its own tag unless they are identical`);
40
- tags.set(message.identifier, message);
41
- }
42
- if ((message instanceof ArgumentMessage || message instanceof ChoiceMessage) && typeof message.identifier === "string") values.add(message.identifier);
41
+ if (message instanceof ElementMessage && typeof message.identifier === "string") claim(tags, message.identifier, message.expression, `Duplicate element tag '${message.identifier}', give each element in a message its own tag unless they are identical`);
42
+ if ((message instanceof ArgumentMessage || message instanceof ChoiceMessage) && typeof message.identifier === "string") claim(values, message.identifier, message.expression, `Duplicate placeholder name '${message.identifier}', give each value in a message its own name unless they are identical`);
43
43
  if (message instanceof CompositeMessage || message instanceof ElementMessage) for (const child of message.children) walk(child);
44
44
  if (message instanceof ChoiceMessage) for (const branch of message.branches) walk(branch.value);
45
45
  }
46
46
  walk(message);
47
47
  for (const tag of tags.keys()) if (values.has(tag)) throw new Error(`Element tag '${tag}' collides with an argument of the same name`);
48
- return /* @__PURE__ */ new Set([...tags.keys(), ...values]);
48
+ return /* @__PURE__ */ new Set([...tags.keys(), ...values.keys()]);
49
49
  }
50
50
  //#endregion
51
51
  //#region src/features/messages/types.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@saykit/config",
3
- "version": "0.0.0-beta-20260729112211",
3
+ "version": "0.0.0-beta-20260729131250",
4
4
  "description": "CLI and configuration tooling for saykit",
5
5
  "keywords": [
6
6
  "cli",