intor-cli 0.0.2 → 0.0.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.
package/README.md CHANGED
@@ -1,46 +1,54 @@
1
- ### Design Guarantees
1
+ <h1 align="center">intor-cli</h1>
2
2
 
3
- - Message types are inferred from the **_default locale_** only.
4
- - All locales are assumed to share the same message shape.
5
- - Locale is treated as a runtime dimension, not a structural one.
6
- - Generated types are intentionally conservative and do not validate locale completeness.
3
+ <div align="center">
4
+
5
+ CLI tool for intor.
7
6
 
8
- ### NOTE
7
+ </div>
9
8
 
10
- ```
11
- (Core Modules)
12
- ├── collect-messages
13
- ├── extract-usages
14
- ├── find-configs
15
- ├── generate-types
16
- ├── infer-schema
17
- ├── validation
18
- ```
9
+ <div align="center">
19
10
 
20
- - pipeline: Collect messages
11
+ [![NPM version](https://img.shields.io/npm/v/intor-cli?style=flat&colorA=000000&colorB=000000)](https://www.npmjs.com/package/intor-cli)
12
+ [![TypeScript](https://img.shields.io/badge/TypeScript-%E2%9C%94-blue?style=flat&colorA=000000&colorB=000000)](https://www.typescriptlang.org/)
13
+ [![License](https://img.shields.io/npm/l/intor-cli?style=flat&colorA=000000&colorB=000000)](LICENSE)
21
14
 
22
- ```
23
- input: none (Detect from environment)
24
- |-> find-configs -> collect-messages
25
- ```
15
+ <table>
16
+ <tr>
17
+ <td align="center">
18
+ <img src="generate-demo.gif" />
19
+ </td>
20
+ <td align="center">
21
+ <img src="check-demo.gif" />
22
+ </td>
23
+ </tr>
24
+ </table>
25
+ </div>
26
26
 
27
- - pipeline: Generate intor schema
27
+ ## Usage
28
28
 
29
- ```
30
- intput: collected messages
31
- |-> infer-schema (write file)
29
+ #### generate
30
+
31
+ ```bash
32
+ npx intor-cli generate
32
33
  ```
33
34
 
34
- - pipeline: Generate intor types
35
+ - Generates TypeScript types and schema artifacts
36
+ - Designed to be safe, deterministic, and non-intrusive
37
+ - Displays runtime message override details during generation
35
38
 
36
- ```
37
- intput: intor schema
38
- |-> generate-types (write file)
39
+ #### check
40
+
41
+ ```bash
42
+ npx intor-cli check
39
43
  ```
40
44
 
41
- - pipeline: Validation
45
+ - Statically extracts translator usages from your codebase
46
+ - Validates preKey, message keys, replacements, and rich tags
47
+ - Reports diagnostics with precise source locations
42
48
 
43
- ```
44
- intput: intor schema
45
- |-> extract-usages -> validation
46
- ```
49
+ ## Design Guarantees
50
+
51
+ - Message types are inferred from the **_default locale_** only.
52
+ - All locales are assumed to share the same message shape.
53
+ - Locale is treated as a runtime dimension, not a structural one.
54
+ - Generated types are intentionally conservative and do not validate locale completeness.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "intor-cli",
3
- "version": "0.0.2",
4
- "description": "Intor CLI",
3
+ "version": "0.0.4",
4
+ "description": "📟 CLI tool for intor",
5
5
  "author": "Yiming Liao",
6
6
  "homepage": "https://github.com/yiming-liao/intor-cli#readme",
7
7
  "repository": {
@@ -12,7 +12,9 @@
12
12
  "url": "https://github.com/yiming-liao/intor-cli/issues"
13
13
  },
14
14
  "keywords": [
15
- "i18n"
15
+ "intor",
16
+ "i18n",
17
+ "cli"
16
18
  ],
17
19
  "license": "MIT",
18
20
  "type": "module",
@@ -41,7 +43,7 @@
41
43
  "@intor/reader-yaml": "0.1.0",
42
44
  "cac": "6.7.14",
43
45
  "fast-glob": "3.3.3",
44
- "intor": "2.3.17",
46
+ "intor": "2.3.19",
45
47
  "logry": "2.1.6",
46
48
  "ora": "9.0.0",
47
49
  "picocolors": "1.1.1",
@@ -1,3 +1,4 @@
1
+ import type { CollectRuntimeMessagesResult, MergeOverrides } from "./types";
1
2
  import type { ExtraExt } from "../../core";
2
3
  import {
3
4
  mergeMessages,
@@ -20,7 +21,7 @@ export async function collectRuntimeMessages(
20
21
  locale: string,
21
22
  exts: Array<ExtraExt> = [],
22
23
  customReaders?: Record<string, string>, // {ext, customReaderFilePath}
23
- ): Promise<LocaleMessages> {
24
+ ): Promise<CollectRuntimeMessagesResult> {
24
25
  // ----------------------------------------------------------------------
25
26
  // Resolve readers
26
27
  // ----------------------------------------------------------------------
@@ -37,6 +38,7 @@ export async function collectRuntimeMessages(
37
38
  // ----------------------------------------------------------------------
38
39
  let serverMessages: LocaleMessages | undefined;
39
40
  let clientMessages: LocaleMessages | undefined;
41
+ const overrides: MergeOverrides[] = [];
40
42
 
41
43
  // Load server-side runtime messages
42
44
  if (config.loader || config.server?.loader) {
@@ -69,8 +71,29 @@ export async function collectRuntimeMessages(
69
71
  const runtimeMessages = mergeMessages(serverMessages, clientMessages, {
70
72
  config,
71
73
  locale,
74
+ onEvent: (event) => {
75
+ overrides.push({
76
+ ...event,
77
+ layer: "client_over_server",
78
+ locale,
79
+ configId: config.id,
80
+ });
81
+ },
72
82
  });
73
83
 
74
84
  // runtime messages > static messages
75
- return mergeMessages(config.messages, runtimeMessages, { config, locale });
85
+ const messages = mergeMessages(config.messages, runtimeMessages, {
86
+ config,
87
+ locale,
88
+ onEvent: (event) => {
89
+ overrides.push({
90
+ ...event,
91
+ layer: "runtime_over_static",
92
+ locale,
93
+ configId: config.id,
94
+ });
95
+ },
96
+ });
97
+
98
+ return { messages, overrides };
76
99
  }
@@ -0,0 +1,12 @@
1
+ import type { DeepMergeOverrideEvent, LocaleMessages } from "intor";
2
+
3
+ export interface CollectRuntimeMessagesResult {
4
+ messages: LocaleMessages;
5
+ overrides: MergeOverrides[];
6
+ }
7
+
8
+ export interface MergeOverrides extends DeepMergeOverrideEvent {
9
+ layer: "client_over_server" | "runtime_over_static";
10
+ locale: string;
11
+ configId: string;
12
+ }
@@ -10,6 +10,7 @@ import {
10
10
  import { printTitle } from "../print-title";
11
11
  import { spinner } from "../spinner";
12
12
  import { printConfigs } from "./print-configs";
13
+ import { printOverrides } from "./print-overrides";
13
14
  import { printSummary } from "./print-summary";
14
15
 
15
16
  export interface GenerateOptions {
@@ -44,16 +45,17 @@ export async function generate({
44
45
 
45
46
  // Runtime mode - Per-config processing
46
47
  for (const { config, filePath } of configEntries) {
47
- const { id, supportedLocales } = config;
48
+ const { id, supportedLocales: locales } = config;
48
49
  printConfigs(id, filePath);
49
- const messages = await collectRuntimeMessages(
50
+ const { messages, overrides } = await collectRuntimeMessages(
50
51
  config,
51
52
  config.defaultLocale,
52
53
  exts,
53
54
  customReaders,
54
55
  );
56
+ printOverrides(overrides);
55
57
  const schemas = inferSchemas(messages[config.defaultLocale]);
56
- buildInputs.push({ id, locales: supportedLocales, schemas });
58
+ buildInputs.push({ id, locales, schemas });
57
59
  }
58
60
 
59
61
  // -----------------------------------------------------------------------
@@ -66,8 +68,7 @@ export async function generate({
66
68
  const { outDir } = await writeGeneratedFiles({ types, schema });
67
69
 
68
70
  spinner.stop();
69
- const duration = performance.now() - start;
70
- printSummary(outDir, duration);
71
+ printSummary(outDir, performance.now() - start);
71
72
  } catch (error) {
72
73
  spinner.stop();
73
74
  console.error(error instanceof Error ? error.message : String(error));
@@ -0,0 +1,38 @@
1
+ import type { MergeOverrides } from "../../core/collect-messages/types";
2
+ import pc from "picocolors";
3
+ import { spinner } from "../spinner";
4
+
5
+ export function printOverrides(overrides: MergeOverrides[]) {
6
+ if (overrides.length === 0) return;
7
+ spinner.stop();
8
+
9
+ console.log(pc.dim(" ↳ Overrides"));
10
+
11
+ // Print deduplicated override entries
12
+ for (const { kind, layer, path, prev, next } of overrides) {
13
+ if (kind === "add") continue;
14
+
15
+ console.log(
16
+ pc.dim(" - ") + pc.dim(`(${formatLayer(layer)}) `) + pc.gray(path),
17
+ formatDiff(prev, next),
18
+ );
19
+ }
20
+
21
+ console.log();
22
+ spinner.start();
23
+ }
24
+
25
+ function formatLayer(layer: "client_over_server" | "runtime_over_static") {
26
+ if (layer === "client_over_server") return "client > server";
27
+ return "runtime > static";
28
+ }
29
+
30
+ function formatDiff(prev: unknown, next: unknown): string | undefined {
31
+ if (typeof prev !== "string" && typeof next !== "string") return;
32
+ return (
33
+ pc.dim("| Prev: ") +
34
+ pc.gray(typeof prev === "string" ? prev : "") +
35
+ pc.dim(", Next: ") +
36
+ pc.gray(typeof next === "string" ? next : "")
37
+ );
38
+ }
@@ -1,9 +1,8 @@
1
1
  import pc from "picocolors";
2
2
 
3
- export function printSummary(outDir: string, ms: number) {
4
- const labelWidth = 18;
5
- const label = (text: string) => pc.dim(text.padEnd(labelWidth));
3
+ const label = (text: string) => pc.dim(text.padEnd(18));
6
4
 
5
+ export function printSummary(outDir: string, ms: number) {
7
6
  console.log();
8
7
  console.log(pc.green(pc.bold("✔ intor generate completed")));
9
8
  console.log();