@intentius/chant 0.0.1
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 +365 -0
- package/package.json +22 -0
- package/src/attrref.test.ts +148 -0
- package/src/attrref.ts +50 -0
- package/src/barrel.test.ts +157 -0
- package/src/barrel.ts +101 -0
- package/src/bench.test.ts +227 -0
- package/src/build.test.ts +437 -0
- package/src/build.ts +425 -0
- package/src/builder.test.ts +312 -0
- package/src/builder.ts +56 -0
- package/src/child-project.ts +44 -0
- package/src/cli/commands/__fixtures__/init-lexicon-output/README.md +26 -0
- package/src/cli/commands/__fixtures__/init-lexicon-output/docs/astro.config.mjs +14 -0
- package/src/cli/commands/__fixtures__/init-lexicon-output/docs/package.json +16 -0
- package/src/cli/commands/__fixtures__/init-lexicon-output/docs/src/content/docs/index.mdx +8 -0
- package/src/cli/commands/__fixtures__/init-lexicon-output/docs/src/content.config.ts +7 -0
- package/src/cli/commands/__fixtures__/init-lexicon-output/docs/tsconfig.json +10 -0
- package/src/cli/commands/__fixtures__/init-lexicon-output/examples/getting-started/.gitkeep +0 -0
- package/src/cli/commands/__fixtures__/init-lexicon-output/justfile +26 -0
- package/src/cli/commands/__fixtures__/init-lexicon-output/package.json +29 -0
- package/src/cli/commands/__fixtures__/init-lexicon-output/src/codegen/docs.ts +25 -0
- package/src/cli/commands/__fixtures__/init-lexicon-output/src/codegen/generate-cli.ts +8 -0
- package/src/cli/commands/__fixtures__/init-lexicon-output/src/codegen/generate.ts +74 -0
- package/src/cli/commands/__fixtures__/init-lexicon-output/src/codegen/naming.ts +33 -0
- package/src/cli/commands/__fixtures__/init-lexicon-output/src/codegen/package.ts +25 -0
- package/src/cli/commands/__fixtures__/init-lexicon-output/src/codegen/rollback.ts +45 -0
- package/src/cli/commands/__fixtures__/init-lexicon-output/src/coverage.ts +11 -0
- package/src/cli/commands/__fixtures__/init-lexicon-output/src/generated/.gitkeep +0 -0
- package/src/cli/commands/__fixtures__/init-lexicon-output/src/import/generator.ts +10 -0
- package/src/cli/commands/__fixtures__/init-lexicon-output/src/import/parser.ts +10 -0
- package/src/cli/commands/__fixtures__/init-lexicon-output/src/index.ts +9 -0
- package/src/cli/commands/__fixtures__/init-lexicon-output/src/lint/rules/index.ts +1 -0
- package/src/cli/commands/__fixtures__/init-lexicon-output/src/lint/rules/sample.ts +18 -0
- package/src/cli/commands/__fixtures__/init-lexicon-output/src/lsp/completions.ts +14 -0
- package/src/cli/commands/__fixtures__/init-lexicon-output/src/lsp/hover.ts +14 -0
- package/src/cli/commands/__fixtures__/init-lexicon-output/src/plugin.ts +110 -0
- package/src/cli/commands/__fixtures__/init-lexicon-output/src/serializer.ts +24 -0
- package/src/cli/commands/__fixtures__/init-lexicon-output/src/spec/fetch.ts +21 -0
- package/src/cli/commands/__fixtures__/init-lexicon-output/src/spec/parse.ts +25 -0
- package/src/cli/commands/__fixtures__/init-lexicon-output/src/validate-cli.ts +4 -0
- package/src/cli/commands/__fixtures__/init-lexicon-output/src/validate.ts +24 -0
- package/src/cli/commands/__fixtures__/init-lexicon-output/tsconfig.json +10 -0
- package/src/cli/commands/__fixtures__/sample-rule.ts +11 -0
- package/src/cli/commands/__snapshots__/init-lexicon.test.ts.snap +222 -0
- package/src/cli/commands/build.test.ts +149 -0
- package/src/cli/commands/build.ts +344 -0
- package/src/cli/commands/diff.test.ts +148 -0
- package/src/cli/commands/diff.ts +221 -0
- package/src/cli/commands/doctor.test.ts +239 -0
- package/src/cli/commands/doctor.ts +224 -0
- package/src/cli/commands/import.test.ts +379 -0
- package/src/cli/commands/import.ts +335 -0
- package/src/cli/commands/init-lexicon.test.ts +297 -0
- package/src/cli/commands/init-lexicon.ts +993 -0
- package/src/cli/commands/init.test.ts +317 -0
- package/src/cli/commands/init.ts +505 -0
- package/src/cli/commands/licenses.ts +165 -0
- package/src/cli/commands/lint.test.ts +332 -0
- package/src/cli/commands/lint.ts +408 -0
- package/src/cli/commands/list.test.ts +100 -0
- package/src/cli/commands/list.ts +108 -0
- package/src/cli/commands/update.test.ts +38 -0
- package/src/cli/commands/update.ts +207 -0
- package/src/cli/conflict-check.test.ts +255 -0
- package/src/cli/conflict-check.ts +89 -0
- package/src/cli/debug.ts +8 -0
- package/src/cli/format.test.ts +140 -0
- package/src/cli/format.ts +133 -0
- package/src/cli/handlers/build.ts +58 -0
- package/src/cli/handlers/dev.ts +38 -0
- package/src/cli/handlers/init.ts +46 -0
- package/src/cli/handlers/lint.ts +36 -0
- package/src/cli/handlers/misc.ts +57 -0
- package/src/cli/handlers/serve.ts +26 -0
- package/src/cli/index.ts +3 -0
- package/src/cli/lsp/capabilities.ts +46 -0
- package/src/cli/lsp/diagnostics.ts +52 -0
- package/src/cli/lsp/server.test.ts +618 -0
- package/src/cli/lsp/server.ts +393 -0
- package/src/cli/main.test.ts +257 -0
- package/src/cli/main.ts +224 -0
- package/src/cli/mcp/resources/context.ts +59 -0
- package/src/cli/mcp/server.test.ts +747 -0
- package/src/cli/mcp/server.ts +402 -0
- package/src/cli/mcp/tools/build.ts +117 -0
- package/src/cli/mcp/tools/import.ts +48 -0
- package/src/cli/mcp/tools/lint.ts +45 -0
- package/src/cli/plugins.test.ts +31 -0
- package/src/cli/plugins.ts +94 -0
- package/src/cli/registry.ts +73 -0
- package/src/cli/reporters/stylish.test.ts +282 -0
- package/src/cli/reporters/stylish.ts +186 -0
- package/src/cli/watch.test.ts +81 -0
- package/src/cli/watch.ts +101 -0
- package/src/codegen/case.test.ts +30 -0
- package/src/codegen/case.ts +11 -0
- package/src/codegen/coverage.ts +167 -0
- package/src/codegen/docs.ts +634 -0
- package/src/codegen/fetch.test.ts +119 -0
- package/src/codegen/fetch.ts +261 -0
- package/src/codegen/generate-registry.test.ts +118 -0
- package/src/codegen/generate-registry.ts +107 -0
- package/src/codegen/generate-runtime-index.test.ts +81 -0
- package/src/codegen/generate-runtime-index.ts +99 -0
- package/src/codegen/generate-typescript.test.ts +146 -0
- package/src/codegen/generate-typescript.ts +161 -0
- package/src/codegen/generate.ts +206 -0
- package/src/codegen/json-patch.test.ts +113 -0
- package/src/codegen/json-patch.ts +151 -0
- package/src/codegen/json-schema.test.ts +196 -0
- package/src/codegen/json-schema.ts +209 -0
- package/src/codegen/naming.ts +201 -0
- package/src/codegen/package.ts +161 -0
- package/src/codegen/rollback.test.ts +92 -0
- package/src/codegen/rollback.ts +115 -0
- package/src/codegen/topo-sort.test.ts +69 -0
- package/src/codegen/topo-sort.ts +46 -0
- package/src/codegen/typecheck.test.ts +37 -0
- package/src/codegen/typecheck.ts +74 -0
- package/src/codegen/validate.test.ts +86 -0
- package/src/codegen/validate.ts +143 -0
- package/src/composite.test.ts +426 -0
- package/src/composite.ts +243 -0
- package/src/config.test.ts +91 -0
- package/src/config.ts +87 -0
- package/src/declarable.test.ts +160 -0
- package/src/declarable.ts +47 -0
- package/src/detectLexicon.test.ts +236 -0
- package/src/detectLexicon.ts +37 -0
- package/src/discovery/cache.test.ts +78 -0
- package/src/discovery/cache.ts +86 -0
- package/src/discovery/collect.test.ts +269 -0
- package/src/discovery/collect.ts +51 -0
- package/src/discovery/cycles.test.ts +238 -0
- package/src/discovery/cycles.ts +107 -0
- package/src/discovery/files.test.ts +154 -0
- package/src/discovery/files.ts +61 -0
- package/src/discovery/graph.test.ts +476 -0
- package/src/discovery/graph.ts +150 -0
- package/src/discovery/import.test.ts +199 -0
- package/src/discovery/import.ts +20 -0
- package/src/discovery/index.test.ts +272 -0
- package/src/discovery/index.ts +132 -0
- package/src/discovery/resolve.test.ts +267 -0
- package/src/discovery/resolve.ts +54 -0
- package/src/errors.test.ts +138 -0
- package/src/errors.ts +86 -0
- package/src/import/base-parser.test.ts +67 -0
- package/src/import/base-parser.ts +48 -0
- package/src/import/generator.ts +21 -0
- package/src/import/ir-utils.test.ts +103 -0
- package/src/import/ir-utils.ts +87 -0
- package/src/import/parser.ts +41 -0
- package/src/index.ts +60 -0
- package/src/intrinsic-interpolation.test.ts +91 -0
- package/src/intrinsic-interpolation.ts +89 -0
- package/src/intrinsic.test.ts +69 -0
- package/src/intrinsic.ts +43 -0
- package/src/lexicon-integrity.test.ts +94 -0
- package/src/lexicon-integrity.ts +69 -0
- package/src/lexicon-manifest.test.ts +101 -0
- package/src/lexicon-manifest.ts +71 -0
- package/src/lexicon-output.test.ts +182 -0
- package/src/lexicon-output.ts +82 -0
- package/src/lexicon-schema.test.ts +239 -0
- package/src/lexicon-schema.ts +144 -0
- package/src/lexicon.ts +212 -0
- package/src/lint/config-overrides.test.ts +254 -0
- package/src/lint/config.test.ts +644 -0
- package/src/lint/config.ts +375 -0
- package/src/lint/declarative.test.ts +256 -0
- package/src/lint/declarative.ts +187 -0
- package/src/lint/engine.test.ts +465 -0
- package/src/lint/engine.ts +172 -0
- package/src/lint/named-checks.test.ts +37 -0
- package/src/lint/named-checks.ts +33 -0
- package/src/lint/parser.test.ts +129 -0
- package/src/lint/parser.ts +42 -0
- package/src/lint/post-synth.test.ts +113 -0
- package/src/lint/post-synth.ts +76 -0
- package/src/lint/presets/relaxed.json +19 -0
- package/src/lint/presets/strict.json +19 -0
- package/src/lint/rule-loader.test.ts +67 -0
- package/src/lint/rule-loader.ts +67 -0
- package/src/lint/rule-options.test.ts +141 -0
- package/src/lint/rule.test.ts +196 -0
- package/src/lint/rule.ts +98 -0
- package/src/lint/rules/barrel-import-style.test.ts +80 -0
- package/src/lint/rules/barrel-import-style.ts +59 -0
- package/src/lint/rules/composite-scope.ts +55 -0
- package/src/lint/rules/cor017-composite-name-match.test.ts +107 -0
- package/src/lint/rules/cor017-composite-name-match.ts +108 -0
- package/src/lint/rules/cor018-composite-prefer-lexicon-type.test.ts +172 -0
- package/src/lint/rules/cor018-composite-prefer-lexicon-type.ts +167 -0
- package/src/lint/rules/declarable-naming-convention.test.ts +69 -0
- package/src/lint/rules/declarable-naming-convention.ts +70 -0
- package/src/lint/rules/enforce-barrel-import.test.ts +169 -0
- package/src/lint/rules/enforce-barrel-import.ts +81 -0
- package/src/lint/rules/enforce-barrel-ref.test.ts +114 -0
- package/src/lint/rules/enforce-barrel-ref.ts +75 -0
- package/src/lint/rules/evl001-non-literal-expression.test.ts +158 -0
- package/src/lint/rules/evl001-non-literal-expression.ts +149 -0
- package/src/lint/rules/evl002-control-flow-resource.test.ts +110 -0
- package/src/lint/rules/evl002-control-flow-resource.ts +61 -0
- package/src/lint/rules/evl003-dynamic-property-access.test.ts +63 -0
- package/src/lint/rules/evl003-dynamic-property-access.ts +41 -0
- package/src/lint/rules/evl004-spread-non-const.test.ts +130 -0
- package/src/lint/rules/evl004-spread-non-const.ts +111 -0
- package/src/lint/rules/evl005-resource-block-body.test.ts +59 -0
- package/src/lint/rules/evl005-resource-block-body.ts +49 -0
- package/src/lint/rules/evl006-barrel-usage.test.ts +63 -0
- package/src/lint/rules/evl006-barrel-usage.ts +95 -0
- package/src/lint/rules/evl007-invalid-siblings.test.ts +87 -0
- package/src/lint/rules/evl007-invalid-siblings.ts +139 -0
- package/src/lint/rules/evl008-unresolvable-barrel-ref.test.ts +118 -0
- package/src/lint/rules/evl008-unresolvable-barrel-ref.ts +140 -0
- package/src/lint/rules/evl009-composite-no-constant.test.ts +162 -0
- package/src/lint/rules/evl009-composite-no-constant.ts +171 -0
- package/src/lint/rules/evl010-composite-no-transform.test.ts +121 -0
- package/src/lint/rules/evl010-composite-no-transform.ts +69 -0
- package/src/lint/rules/export-required.test.ts +213 -0
- package/src/lint/rules/export-required.ts +158 -0
- package/src/lint/rules/file-declarable-limit.test.ts +148 -0
- package/src/lint/rules/file-declarable-limit.ts +96 -0
- package/src/lint/rules/flat-declarations.test.ts +210 -0
- package/src/lint/rules/flat-declarations.ts +70 -0
- package/src/lint/rules/index.ts +99 -0
- package/src/lint/rules/no-cyclic-declarable-ref.test.ts +135 -0
- package/src/lint/rules/no-cyclic-declarable-ref.ts +178 -0
- package/src/lint/rules/no-redundant-type-import.test.ts +129 -0
- package/src/lint/rules/no-redundant-type-import.ts +85 -0
- package/src/lint/rules/no-redundant-value-cast.test.ts +51 -0
- package/src/lint/rules/no-redundant-value-cast.ts +46 -0
- package/src/lint/rules/no-string-ref.test.ts +100 -0
- package/src/lint/rules/no-string-ref.ts +66 -0
- package/src/lint/rules/no-unused-declarable-import.test.ts +74 -0
- package/src/lint/rules/no-unused-declarable-import.ts +103 -0
- package/src/lint/rules/no-unused-declarable.test.ts +134 -0
- package/src/lint/rules/no-unused-declarable.ts +118 -0
- package/src/lint/rules/prefer-namespace-import.test.ts +102 -0
- package/src/lint/rules/prefer-namespace-import.ts +63 -0
- package/src/lint/rules/single-concern-file.test.ts +156 -0
- package/src/lint/rules/single-concern-file.ts +98 -0
- package/src/lint/rules/stale-barrel-types.ts +60 -0
- package/src/lint/selectors.test.ts +113 -0
- package/src/lint/selectors.ts +188 -0
- package/src/lsp/lexicon-providers.ts +191 -0
- package/src/lsp/types.ts +79 -0
- package/src/mcp/types.ts +22 -0
- package/src/project/scan.test.ts +178 -0
- package/src/project/scan.ts +182 -0
- package/src/project/sync.test.ts +87 -0
- package/src/project/sync.ts +46 -0
- package/src/project-validation.test.ts +64 -0
- package/src/project-validation.ts +79 -0
- package/src/pseudo-parameter.test.ts +39 -0
- package/src/pseudo-parameter.ts +47 -0
- package/src/runtime.ts +68 -0
- package/src/serializer-walker.test.ts +124 -0
- package/src/serializer-walker.ts +83 -0
- package/src/serializer.ts +42 -0
- package/src/sort.test.ts +290 -0
- package/src/sort.ts +58 -0
- package/src/stack-output.ts +82 -0
- package/src/types.test.ts +307 -0
- package/src/types.ts +46 -0
- package/src/utils.test.ts +195 -0
- package/src/utils.ts +46 -0
- package/src/validation.test.ts +308 -0
- package/src/validation.ts +50 -0
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ANSI color codes for terminal output
|
|
3
|
+
*/
|
|
4
|
+
const colors = {
|
|
5
|
+
red: "\x1b[31m",
|
|
6
|
+
yellow: "\x1b[33m",
|
|
7
|
+
green: "\x1b[32m",
|
|
8
|
+
cyan: "\x1b[36m",
|
|
9
|
+
gray: "\x1b[90m",
|
|
10
|
+
reset: "\x1b[0m",
|
|
11
|
+
bold: "\x1b[1m",
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Check if colors should be used (respects NO_COLOR env var)
|
|
16
|
+
*/
|
|
17
|
+
function useColors(): boolean {
|
|
18
|
+
return !process.env.NO_COLOR && process.stdout.isTTY !== false;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Apply color if colors are enabled
|
|
23
|
+
*/
|
|
24
|
+
function color(text: string, colorCode: string): string {
|
|
25
|
+
if (!useColors()) return text;
|
|
26
|
+
return `${colorCode}${text}${colors.reset}`;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Format an error with ANSI colors
|
|
31
|
+
* Shows file:line:column in cyan, error in red
|
|
32
|
+
*/
|
|
33
|
+
export function formatError(error: {
|
|
34
|
+
file?: string;
|
|
35
|
+
line?: number;
|
|
36
|
+
column?: number;
|
|
37
|
+
message: string;
|
|
38
|
+
name?: string;
|
|
39
|
+
hint?: string;
|
|
40
|
+
}): string {
|
|
41
|
+
const parts: string[] = [];
|
|
42
|
+
|
|
43
|
+
// Location prefix
|
|
44
|
+
if (error.file) {
|
|
45
|
+
let location = error.file;
|
|
46
|
+
if (error.line !== undefined) {
|
|
47
|
+
location += `:${error.line}`;
|
|
48
|
+
if (error.column !== undefined) {
|
|
49
|
+
location += `:${error.column}`;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
parts.push(color(location, colors.cyan));
|
|
53
|
+
parts.push(" - ");
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Error type
|
|
57
|
+
parts.push(color("error", colors.red));
|
|
58
|
+
parts.push(": ");
|
|
59
|
+
|
|
60
|
+
// Message
|
|
61
|
+
parts.push(error.message);
|
|
62
|
+
|
|
63
|
+
// Hint
|
|
64
|
+
if (error.hint) {
|
|
65
|
+
parts.push("\n ");
|
|
66
|
+
parts.push(color(error.hint, colors.gray));
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return parts.join("");
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Format a warning with ANSI colors
|
|
74
|
+
* Shows file:line:column in cyan, warning in yellow
|
|
75
|
+
*/
|
|
76
|
+
export function formatWarning(warning: {
|
|
77
|
+
file?: string;
|
|
78
|
+
line?: number;
|
|
79
|
+
column?: number;
|
|
80
|
+
message: string;
|
|
81
|
+
hint?: string;
|
|
82
|
+
}): string {
|
|
83
|
+
const parts: string[] = [];
|
|
84
|
+
|
|
85
|
+
// Location prefix
|
|
86
|
+
if (warning.file) {
|
|
87
|
+
let location = warning.file;
|
|
88
|
+
if (warning.line !== undefined) {
|
|
89
|
+
location += `:${warning.line}`;
|
|
90
|
+
if (warning.column !== undefined) {
|
|
91
|
+
location += `:${warning.column}`;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
parts.push(color(location, colors.cyan));
|
|
95
|
+
parts.push(" - ");
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Warning type
|
|
99
|
+
parts.push(color("warning", colors.yellow));
|
|
100
|
+
parts.push(": ");
|
|
101
|
+
|
|
102
|
+
// Message
|
|
103
|
+
parts.push(warning.message);
|
|
104
|
+
|
|
105
|
+
// Hint
|
|
106
|
+
if (warning.hint) {
|
|
107
|
+
parts.push("\n ");
|
|
108
|
+
parts.push(color(warning.hint, colors.gray));
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
return parts.join("");
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Format a success message in green
|
|
116
|
+
*/
|
|
117
|
+
export function formatSuccess(message: string): string {
|
|
118
|
+
return color(message, colors.green);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Format an info message in gray
|
|
123
|
+
*/
|
|
124
|
+
export function formatInfo(message: string): string {
|
|
125
|
+
return color(message, colors.gray);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Format a count/stat in bold
|
|
130
|
+
*/
|
|
131
|
+
export function formatBold(text: string): string {
|
|
132
|
+
return color(text, colors.bold);
|
|
133
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { buildCommand, buildCommandWatch, printErrors, printWarnings } from "../commands/build";
|
|
2
|
+
import { formatInfo } from "../format";
|
|
3
|
+
import type { CommandContext } from "../registry";
|
|
4
|
+
|
|
5
|
+
export async function runBuild(ctx: CommandContext): Promise<number> {
|
|
6
|
+
const { args, plugins } = ctx;
|
|
7
|
+
let { serializers } = ctx;
|
|
8
|
+
|
|
9
|
+
// Filter to a single lexicon when --lexicon is specified
|
|
10
|
+
if (args.lexicon) {
|
|
11
|
+
serializers = serializers.filter((s) => s.name === args.lexicon);
|
|
12
|
+
if (serializers.length === 0) {
|
|
13
|
+
console.error(`No serializer found for lexicon "${args.lexicon}". Available: ${ctx.serializers.map((s) => s.name).join(", ")}`);
|
|
14
|
+
return 1;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const buildFormat = (args.format || "json") as "json" | "yaml";
|
|
19
|
+
if (buildFormat !== "json" && buildFormat !== "yaml") {
|
|
20
|
+
console.error(`Invalid format for build: ${buildFormat}. Expected 'json' or 'yaml'.`);
|
|
21
|
+
return 1;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if (args.watch) {
|
|
25
|
+
const cleanup = buildCommandWatch({
|
|
26
|
+
path: args.path,
|
|
27
|
+
output: args.output,
|
|
28
|
+
format: buildFormat,
|
|
29
|
+
serializers,
|
|
30
|
+
plugins,
|
|
31
|
+
});
|
|
32
|
+
process.on("SIGINT", () => {
|
|
33
|
+
cleanup();
|
|
34
|
+
console.error(formatInfo("\nWatch mode stopped."));
|
|
35
|
+
process.exit(0);
|
|
36
|
+
});
|
|
37
|
+
await new Promise(() => {});
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const result = await buildCommand({
|
|
41
|
+
path: args.path,
|
|
42
|
+
output: args.output,
|
|
43
|
+
format: buildFormat,
|
|
44
|
+
serializers,
|
|
45
|
+
plugins,
|
|
46
|
+
verbose: args.verbose,
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
// When --lexicon filters to a subset, suppress "No serializer" warnings for excluded lexicons
|
|
50
|
+
let warnings = result.warnings;
|
|
51
|
+
if (args.lexicon) {
|
|
52
|
+
warnings = warnings.filter((w) => !w.includes('No serializer found for lexicon'));
|
|
53
|
+
}
|
|
54
|
+
printWarnings(warnings);
|
|
55
|
+
printErrors(result.errors);
|
|
56
|
+
|
|
57
|
+
return result.success ? 0 : 1;
|
|
58
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { formatError, formatSuccess } from "../format";
|
|
2
|
+
import type { CommandContext } from "../registry";
|
|
3
|
+
|
|
4
|
+
export async function runDevGenerate(ctx: CommandContext): Promise<number> {
|
|
5
|
+
for (const plugin of ctx.plugins) {
|
|
6
|
+
await plugin.generate({ verbose: ctx.args.verbose });
|
|
7
|
+
console.error(formatSuccess(`${plugin.name}: generate complete`));
|
|
8
|
+
await plugin.validate({ verbose: ctx.args.verbose });
|
|
9
|
+
console.error(formatSuccess(`${plugin.name}: validate complete`));
|
|
10
|
+
await plugin.coverage({ verbose: ctx.args.verbose });
|
|
11
|
+
console.error(formatSuccess(`${plugin.name}: coverage complete`));
|
|
12
|
+
}
|
|
13
|
+
return 0;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export async function runDevPublish(ctx: CommandContext): Promise<number> {
|
|
17
|
+
for (const plugin of ctx.plugins) {
|
|
18
|
+
await plugin.package({ verbose: ctx.args.verbose, force: ctx.args.force });
|
|
19
|
+
console.error(formatSuccess(`${plugin.name}: publish complete`));
|
|
20
|
+
}
|
|
21
|
+
return 0;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export async function runDevRollback(ctx: CommandContext): Promise<number> {
|
|
25
|
+
for (const plugin of ctx.plugins) {
|
|
26
|
+
await plugin.rollback({ verbose: ctx.args.verbose });
|
|
27
|
+
console.error(formatSuccess(`${plugin.name}: rollback complete`));
|
|
28
|
+
}
|
|
29
|
+
return 0;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export async function runDevUnknown(ctx: CommandContext): Promise<number> {
|
|
33
|
+
console.error(formatError({
|
|
34
|
+
message: `Unknown dev subcommand: ${ctx.args.path}`,
|
|
35
|
+
hint: "Available: chant dev generate, chant dev publish, chant dev rollback",
|
|
36
|
+
}));
|
|
37
|
+
return 1;
|
|
38
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { formatError } from "../format";
|
|
2
|
+
import type { CommandContext } from "../registry";
|
|
3
|
+
|
|
4
|
+
export async function runInit(ctx: CommandContext): Promise<number> {
|
|
5
|
+
const { args } = ctx;
|
|
6
|
+
|
|
7
|
+
if (!args.lexicon) {
|
|
8
|
+
console.error(formatError({
|
|
9
|
+
message: "Missing --lexicon flag",
|
|
10
|
+
hint: "Usage: chant init --lexicon <name>",
|
|
11
|
+
}));
|
|
12
|
+
return 1;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const { initCommand, printInitResult } = await import("../commands/init");
|
|
16
|
+
const result = await initCommand({
|
|
17
|
+
path: args.path === "." ? undefined : args.path,
|
|
18
|
+
lexicon: args.lexicon,
|
|
19
|
+
force: args.force,
|
|
20
|
+
skipInstall: true,
|
|
21
|
+
});
|
|
22
|
+
await printInitResult(result, { skipInstall: false, cwd: args.path });
|
|
23
|
+
return result.success ? 0 : 1;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export async function runInitLexicon(ctx: CommandContext): Promise<number> {
|
|
27
|
+
const { args } = ctx;
|
|
28
|
+
|
|
29
|
+
const name = args.extraPositional;
|
|
30
|
+
if (!name) {
|
|
31
|
+
console.error(formatError({
|
|
32
|
+
message: "Missing lexicon name",
|
|
33
|
+
hint: "Usage: chant init lexicon <name> [path]",
|
|
34
|
+
}));
|
|
35
|
+
return 1;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const { initLexiconCommand, printInitLexiconResult } = await import("../commands/init-lexicon");
|
|
39
|
+
const result = await initLexiconCommand({
|
|
40
|
+
name,
|
|
41
|
+
path: args.extraPositional2,
|
|
42
|
+
force: args.force,
|
|
43
|
+
});
|
|
44
|
+
await printInitLexiconResult(result);
|
|
45
|
+
return result.success ? 0 : 1;
|
|
46
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { lintCommand, lintCommandWatch, printLintResult } from "../commands/lint";
|
|
2
|
+
import { formatInfo } from "../format";
|
|
3
|
+
import type { CommandContext } from "../registry";
|
|
4
|
+
|
|
5
|
+
export async function runLint(ctx: CommandContext): Promise<number> {
|
|
6
|
+
const { args } = ctx;
|
|
7
|
+
|
|
8
|
+
const lintFormat = (args.format || "stylish") as "stylish" | "json" | "sarif";
|
|
9
|
+
if (lintFormat !== "stylish" && lintFormat !== "json" && lintFormat !== "sarif") {
|
|
10
|
+
console.error(`Invalid format for lint: ${lintFormat}. Expected 'stylish', 'json', or 'sarif'.`);
|
|
11
|
+
return 1;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
if (args.watch) {
|
|
15
|
+
const cleanup = lintCommandWatch({
|
|
16
|
+
path: args.path,
|
|
17
|
+
fix: args.fix,
|
|
18
|
+
format: lintFormat,
|
|
19
|
+
});
|
|
20
|
+
process.on("SIGINT", () => {
|
|
21
|
+
cleanup();
|
|
22
|
+
console.error(formatInfo("\nWatch mode stopped."));
|
|
23
|
+
process.exit(0);
|
|
24
|
+
});
|
|
25
|
+
await new Promise(() => {});
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const result = await lintCommand({
|
|
29
|
+
path: args.path,
|
|
30
|
+
fix: args.fix,
|
|
31
|
+
format: lintFormat,
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
printLintResult(result);
|
|
35
|
+
return result.success ? 0 : 1;
|
|
36
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { listCommand, printListResult } from "../commands/list";
|
|
2
|
+
import { importCommand, printImportResult } from "../commands/import";
|
|
3
|
+
import { formatError, formatSuccess } from "../format";
|
|
4
|
+
import type { CommandContext } from "../registry";
|
|
5
|
+
|
|
6
|
+
export async function runList(ctx: CommandContext): Promise<number> {
|
|
7
|
+
const { args } = ctx;
|
|
8
|
+
const listFormat = (args.format || "text") as "text" | "json";
|
|
9
|
+
if (listFormat !== "text" && listFormat !== "json") {
|
|
10
|
+
console.error(`Invalid format for list: ${listFormat}. Expected 'text' or 'json'.`);
|
|
11
|
+
return 1;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const result = await listCommand({
|
|
15
|
+
path: args.path,
|
|
16
|
+
format: listFormat,
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
printListResult(result);
|
|
20
|
+
return result.success ? 0 : 1;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export async function runImport(ctx: CommandContext): Promise<number> {
|
|
24
|
+
const result = await importCommand({
|
|
25
|
+
templatePath: ctx.args.path,
|
|
26
|
+
output: ctx.args.output,
|
|
27
|
+
force: ctx.args.force,
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
printImportResult(result);
|
|
31
|
+
return result.success ? 0 : 1;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export async function runUpdate(ctx: CommandContext): Promise<number> {
|
|
35
|
+
const { updateCommand, printUpdateResult } = await import("../commands/update");
|
|
36
|
+
const result = await updateCommand({ path: ctx.args.path });
|
|
37
|
+
printUpdateResult(result);
|
|
38
|
+
return result.success ? 0 : 1;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export async function runDoctor(ctx: CommandContext): Promise<number> {
|
|
42
|
+
const { doctorCommand } = await import("../commands/doctor");
|
|
43
|
+
const report = await doctorCommand(ctx.args.path);
|
|
44
|
+
|
|
45
|
+
for (const check of report.checks) {
|
|
46
|
+
const icon = check.status === "pass" ? "OK" : check.status === "warn" ? "WARN" : "FAIL";
|
|
47
|
+
const msg = check.message ? ` — ${check.message}` : "";
|
|
48
|
+
console.error(` [${icon}] ${check.name}${msg}`);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (!report.success) {
|
|
52
|
+
console.error(formatError({ message: "Doctor found issues" }));
|
|
53
|
+
} else {
|
|
54
|
+
console.error(formatSuccess("All checks passed"));
|
|
55
|
+
}
|
|
56
|
+
return report.success ? 0 : 1;
|
|
57
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { formatError } from "../format";
|
|
2
|
+
import type { CommandContext } from "../registry";
|
|
3
|
+
|
|
4
|
+
export async function runServeLsp(ctx: CommandContext): Promise<number> {
|
|
5
|
+
const { LspServer } = await import("../lsp/server");
|
|
6
|
+
const server = new LspServer(ctx.plugins);
|
|
7
|
+
await server.start();
|
|
8
|
+
await new Promise(() => {});
|
|
9
|
+
return 0; // unreachable
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export async function runServeMcp(ctx: CommandContext): Promise<number> {
|
|
13
|
+
const { McpServer } = await import("../mcp/server");
|
|
14
|
+
const server = new McpServer(ctx.plugins);
|
|
15
|
+
await server.start();
|
|
16
|
+
await new Promise(() => {});
|
|
17
|
+
return 0; // unreachable
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export async function runServeUnknown(ctx: CommandContext): Promise<number> {
|
|
21
|
+
console.error(formatError({
|
|
22
|
+
message: `Unknown serve subcommand: ${ctx.args.path}`,
|
|
23
|
+
hint: "Available: chant serve lsp, chant serve mcp",
|
|
24
|
+
}));
|
|
25
|
+
return 1;
|
|
26
|
+
}
|
package/src/cli/index.ts
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { LexiconPlugin } from "../../lexicon";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* LSP server capabilities, conditionally advertised based on loaded plugins.
|
|
5
|
+
*/
|
|
6
|
+
export interface LspCapabilities {
|
|
7
|
+
textDocumentSync: number;
|
|
8
|
+
completionProvider?: { triggerCharacters: string[] };
|
|
9
|
+
hoverProvider?: boolean;
|
|
10
|
+
codeActionProvider?: boolean;
|
|
11
|
+
diagnosticProvider?: { interFileDependencies: boolean; workspaceDiagnostics: boolean };
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Compute LSP capabilities based on which plugins implement providers.
|
|
16
|
+
*/
|
|
17
|
+
export function computeCapabilities(plugins: LexiconPlugin[]): LspCapabilities {
|
|
18
|
+
const hasCompletion = plugins.some((p) => p.completionProvider !== undefined);
|
|
19
|
+
const hasHover = plugins.some((p) => p.hoverProvider !== undefined);
|
|
20
|
+
const hasCodeAction = plugins.some((p) => p.codeActionProvider !== undefined);
|
|
21
|
+
|
|
22
|
+
const capabilities: LspCapabilities = {
|
|
23
|
+
// Full sync — client sends full document content on open/change
|
|
24
|
+
textDocumentSync: 1,
|
|
25
|
+
diagnosticProvider: {
|
|
26
|
+
interFileDependencies: false,
|
|
27
|
+
workspaceDiagnostics: false,
|
|
28
|
+
},
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
if (hasCompletion) {
|
|
32
|
+
capabilities.completionProvider = {
|
|
33
|
+
triggerCharacters: [".", " ", '"', "'", "`", "("],
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (hasHover) {
|
|
38
|
+
capabilities.hoverProvider = true;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (hasCodeAction) {
|
|
42
|
+
capabilities.codeActionProvider = true;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return capabilities;
|
|
46
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { LintDiagnostic, Severity } from "../../lint/rule";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* LSP diagnostic as returned in textDocument/publishDiagnostics.
|
|
5
|
+
*/
|
|
6
|
+
export interface LspDiagnostic {
|
|
7
|
+
range: {
|
|
8
|
+
start: { line: number; character: number };
|
|
9
|
+
end: { line: number; character: number };
|
|
10
|
+
};
|
|
11
|
+
severity: number;
|
|
12
|
+
code?: string;
|
|
13
|
+
source: string;
|
|
14
|
+
message: string;
|
|
15
|
+
data?: { ruleId: string; fix?: unknown };
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Map chant severity to LSP DiagnosticSeverity (1=Error, 2=Warning, 3=Info, 4=Hint)
|
|
20
|
+
*/
|
|
21
|
+
function toLspSeverity(severity: Severity): number {
|
|
22
|
+
switch (severity) {
|
|
23
|
+
case "error":
|
|
24
|
+
return 1;
|
|
25
|
+
case "warning":
|
|
26
|
+
return 2;
|
|
27
|
+
case "info":
|
|
28
|
+
return 3;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Convert chant LintDiagnostics to LSP diagnostics.
|
|
34
|
+
* Converts 1-based lines/columns to 0-based.
|
|
35
|
+
*/
|
|
36
|
+
export function toLspDiagnostics(diagnostics: LintDiagnostic[]): LspDiagnostic[] {
|
|
37
|
+
return diagnostics.map((d) => {
|
|
38
|
+
const line = Math.max(0, d.line - 1);
|
|
39
|
+
const character = Math.max(0, d.column - 1);
|
|
40
|
+
return {
|
|
41
|
+
range: {
|
|
42
|
+
start: { line, character },
|
|
43
|
+
end: { line, character },
|
|
44
|
+
},
|
|
45
|
+
severity: toLspSeverity(d.severity),
|
|
46
|
+
code: d.ruleId,
|
|
47
|
+
source: "chant",
|
|
48
|
+
message: d.message,
|
|
49
|
+
data: d.fix ? { ruleId: d.ruleId, fix: d.fix } : { ruleId: d.ruleId },
|
|
50
|
+
};
|
|
51
|
+
});
|
|
52
|
+
}
|