intor-cli 0.0.2 → 0.0.3
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 +41 -33
- package/package.json +6 -4
- package/src/core/collect-messages/collect-runtime-messages.ts +25 -2
- package/src/core/collect-messages/types.ts +12 -0
- package/src/features/generate/generate.ts +6 -5
- package/src/features/generate/print-overrides.ts +36 -0
- package/src/features/generate/print-summary.ts +2 -3
package/README.md
CHANGED
|
@@ -1,46 +1,54 @@
|
|
|
1
|
-
|
|
1
|
+
<h1 align="center">intor-cli</h1>
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
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
|
-
|
|
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
|
-
-
|
|
11
|
+
[](https://www.npmjs.com/package/intor-cli)
|
|
12
|
+
[](https://www.typescriptlang.org/)
|
|
13
|
+
[](LICENSE)
|
|
21
14
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
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
|
-
|
|
27
|
+
## Usage
|
|
28
28
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
29
|
+
#### generate
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
npx intor-cli generate
|
|
32
33
|
```
|
|
33
34
|
|
|
34
|
-
-
|
|
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
|
-
|
|
38
|
-
|
|
39
|
+
#### check
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
npx intor-cli check
|
|
39
43
|
```
|
|
40
44
|
|
|
41
|
-
-
|
|
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
|
-
|
|
45
|
-
|
|
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.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.0.3",
|
|
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
|
-
"
|
|
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.
|
|
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<
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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,36 @@
|
|
|
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 { layer, path, prev, next } of overrides) {
|
|
13
|
+
console.log(
|
|
14
|
+
pc.dim(" - ") + pc.dim(`(${formatLayer(layer)}) `) + pc.gray(path),
|
|
15
|
+
formatDiff(prev, next),
|
|
16
|
+
);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
console.log();
|
|
20
|
+
spinner.start();
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function formatLayer(layer: "client_over_server" | "runtime_over_static") {
|
|
24
|
+
if (layer === "client_over_server") return "client > server";
|
|
25
|
+
return "runtime > static";
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function formatDiff(prev: unknown, next: unknown): string | undefined {
|
|
29
|
+
if (typeof prev !== "string" && typeof next !== "string") return;
|
|
30
|
+
return (
|
|
31
|
+
pc.dim("| Prev: ") +
|
|
32
|
+
pc.gray(typeof prev === "string" ? prev : "") +
|
|
33
|
+
pc.dim(", Next: ") +
|
|
34
|
+
pc.gray(typeof next === "string" ? next : "")
|
|
35
|
+
);
|
|
36
|
+
}
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import pc from "picocolors";
|
|
2
2
|
|
|
3
|
-
|
|
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();
|