intor-cli 0.0.10 → 0.0.11

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "intor-cli",
3
- "version": "0.0.10",
3
+ "version": "0.0.11",
4
4
  "description": "📟 CLI tool for intor",
5
5
  "author": "Yiming Liao",
6
6
  "homepage": "https://github.com/yiming-liao/intor-cli#readme",
@@ -1,5 +1,6 @@
1
1
  import type { BuildInput } from "../types";
2
2
  import { appendHeader, appendConfigBlock, appendFooter } from "./output";
3
+ import { normalizeRichInferNode } from "./utils/normalize-rich-infer-node";
3
4
  import { renderInferNode } from "./utils/render-infer-node";
4
5
 
5
6
  const GENERATED_INTERFACE_NAME = "IntorGeneratedTypes";
@@ -18,7 +19,9 @@ export function buildTypes(inputs: BuildInput[]): string {
18
19
  const localesType = input.locales.map((l) => `"${l}"`).join(" | ");
19
20
  const messagesType = renderInferNode(input.schemas.messagesSchema);
20
21
  const replacementsType = renderInferNode(input.schemas.replacementsSchema);
21
- const richType = renderInferNode(input.schemas.richSchema);
22
+ const richType = renderInferNode(
23
+ normalizeRichInferNode(input.schemas.richSchema),
24
+ );
22
25
 
23
26
  if (index === 0) {
24
27
  appendConfigBlock(lines, {
@@ -0,0 +1,40 @@
1
+ import type { InferNode } from "../../../core";
2
+
3
+ /**
4
+ * Normalize inferred rich schema before type emission.
5
+ *
6
+ * Rich schema normalization rules:
7
+ *
8
+ * - `none` means: the tag exists but has no nested structure
9
+ * → normalize to `record` so it emits `Record<string, never>`
10
+ * → this preserves tag presence while preventing arbitrary indexing
11
+ *
12
+ * - `object` nodes are recursively normalized
13
+ *
14
+ * This normalization is required to keep rich tag autocompletion working.
15
+ */
16
+ export function normalizeRichInferNode(node: InferNode): InferNode {
17
+ // Leaf rich tag: presence marker only
18
+ if (node.kind === "none") {
19
+ return {
20
+ kind: "record",
21
+ };
22
+ }
23
+
24
+ // Recursively normalize nested rich tag trees
25
+ if (node.kind === "object") {
26
+ return {
27
+ kind: "object",
28
+ properties: Object.fromEntries(
29
+ Object.entries(node.properties).map(([key, child]) => [
30
+ key,
31
+ normalizeRichInferNode(child),
32
+ ]),
33
+ ),
34
+ };
35
+ }
36
+
37
+ // Other kinds should not appear in rich schema,
38
+ // but are passed through defensively
39
+ return node;
40
+ }
@@ -13,7 +13,9 @@ export function renderInferNode(node: InferNode, indentLevel = 4): string {
13
13
  return `${renderInferNode(node.element, indentLevel)}[]`;
14
14
  }
15
15
  case "record": {
16
- return "Record<string, unknown>";
16
+ // Rich leaf nodes must be non-indexable to preserve
17
+ // key narrowing and autocomplete behavior
18
+ return "Record<string, never>";
17
19
  }
18
20
  case "object": {
19
21
  return `{