@intentius/chant 0.0.18 → 0.0.24

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.
Files changed (87) hide show
  1. package/bin/chant +4 -1
  2. package/package.json +20 -1
  3. package/src/build.test.ts +4 -2
  4. package/src/build.ts +3 -0
  5. package/src/builder.test.ts +3 -0
  6. package/src/cli/commands/__fixtures__/init-lexicon-output/docs/astro.config.mjs +0 -3
  7. package/src/cli/commands/build.ts +5 -12
  8. package/src/cli/commands/diff.test.ts +2 -1
  9. package/src/cli/commands/diff.ts +2 -1
  10. package/src/cli/commands/init-lexicon/templates/codegen.ts +188 -0
  11. package/src/cli/commands/init-lexicon/templates/docs.ts +81 -0
  12. package/src/cli/commands/init-lexicon/templates/examples.ts +35 -0
  13. package/src/cli/commands/init-lexicon/templates/lint.ts +30 -0
  14. package/src/cli/commands/init-lexicon/templates/lsp.ts +39 -0
  15. package/src/cli/commands/init-lexicon/templates/plugin.ts +110 -0
  16. package/src/cli/commands/init-lexicon/templates/project.ts +182 -0
  17. package/src/cli/commands/init-lexicon/templates/spec.ts +57 -0
  18. package/src/cli/commands/init-lexicon/templates/tests.ts +70 -0
  19. package/src/cli/commands/init-lexicon.test.ts +0 -9
  20. package/src/cli/commands/init-lexicon.ts +12 -868
  21. package/src/cli/commands/init.ts +2 -20
  22. package/src/cli/conflict-check.test.ts +43 -0
  23. package/src/cli/handlers/build.ts +3 -3
  24. package/src/cli/handlers/lint.ts +2 -2
  25. package/src/cli/handlers/spell.ts +396 -0
  26. package/src/cli/handlers/state.ts +230 -0
  27. package/src/cli/lsp/server.test.ts +4 -0
  28. package/src/cli/main.ts +37 -3
  29. package/src/cli/mcp/resource-handlers.ts +227 -0
  30. package/src/cli/mcp/server.test.ts +13 -9
  31. package/src/cli/mcp/server.ts +24 -199
  32. package/src/cli/mcp/state-tools.ts +138 -0
  33. package/src/cli/mcp/tools/build.ts +2 -1
  34. package/src/cli/mcp/types.ts +45 -0
  35. package/src/cli/plugins.ts +1 -1
  36. package/src/cli/reporters/stylish.test.ts +2 -2
  37. package/src/cli/reporters/stylish.ts +1 -1
  38. package/src/codegen/docs-file-markers.ts +69 -0
  39. package/src/codegen/docs-rule-scanning.ts +159 -0
  40. package/src/codegen/docs-sections.ts +159 -0
  41. package/src/codegen/docs-sidebar.ts +56 -0
  42. package/src/codegen/docs-types.ts +79 -0
  43. package/src/codegen/docs.ts +9 -495
  44. package/src/composite.test.ts +76 -1
  45. package/src/composite.ts +37 -0
  46. package/src/config.ts +4 -0
  47. package/src/declarable.test.ts +2 -1
  48. package/src/declarable.ts +1 -1
  49. package/src/discovery/collect.test.ts +34 -0
  50. package/src/discovery/collect.ts +12 -0
  51. package/src/discovery/graph.test.ts +40 -0
  52. package/src/discovery/import.test.ts +5 -5
  53. package/src/discovery/resolve.test.ts +20 -0
  54. package/src/discovery/resolve.ts +2 -2
  55. package/src/index.ts +2 -0
  56. package/src/lexicon-plugin-helpers.ts +130 -0
  57. package/src/lexicon.ts +24 -0
  58. package/src/lint/rule-options.test.ts +3 -3
  59. package/src/lint/rule-registry.test.ts +1 -1
  60. package/src/lint/rules/composite-scope.ts +1 -1
  61. package/src/serializer-walker.ts +2 -1
  62. package/src/spell/discovery.ts +183 -0
  63. package/src/spell/index.ts +3 -0
  64. package/src/spell/prompt.ts +133 -0
  65. package/src/spell/types.ts +89 -0
  66. package/src/state/digest.ts +88 -0
  67. package/src/state/git.ts +317 -0
  68. package/src/state/index.ts +4 -0
  69. package/src/state/snapshot.ts +179 -0
  70. package/src/state/types.ts +59 -0
  71. package/src/toml-emit.ts +182 -0
  72. package/src/toml-parse.ts +370 -0
  73. package/src/toml-utils.ts +60 -0
  74. package/src/toml.ts +5 -602
  75. package/src/types.ts +2 -1
  76. package/src/utils.test.ts +16 -3
  77. package/src/utils.ts +31 -1
  78. package/src/validation.test.ts +11 -0
  79. package/src/cli/commands/__fixtures__/init-lexicon-output/docs/src/content/docs/getting-started.mdx +0 -6
  80. package/src/cli/commands/__fixtures__/init-lexicon-output/docs/src/content/docs/lint-rules.mdx +0 -6
  81. package/src/cli/commands/__fixtures__/init-lexicon-output/docs/src/content/docs/serialization.mdx +0 -6
  82. package/src/cli/commands/__fixtures__/init-lexicon-output/src/actions/.gitkeep +0 -0
  83. package/src/cli/commands/__fixtures__/init-lexicon-output/src/composites/.gitkeep +0 -0
  84. package/src/cli/commands/__fixtures__/init-lexicon-output/src/coverage.ts +0 -11
  85. package/src/cli/commands/__fixtures__/init-lexicon-output/src/import/generator.ts +0 -10
  86. package/src/cli/commands/__fixtures__/init-lexicon-output/src/import/parser.ts +0 -10
  87. package/src/cli/commands/__fixtures__/init-lexicon-output/src/lint/post-synth/.gitkeep +0 -0
package/src/utils.test.ts CHANGED
@@ -14,15 +14,17 @@ describe("LOGICAL_NAME_SYMBOL", () => {
14
14
  });
15
15
 
16
16
  test("uses Symbol.for for global registry", () => {
17
- expect(LOGICAL_NAME_SYMBOL).toBe(Symbol.for("chant.logicalName"));
17
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
18
+ expect(LOGICAL_NAME_SYMBOL).toBe(Symbol.for("chant.logicalName") as any);
18
19
  });
19
20
  });
20
21
 
21
22
  describe("getAttributes", () => {
22
23
  test("returns empty array for entity with no AttrRef properties", () => {
23
- const entity: Declarable = {
24
+ const entity = {
25
+ lexicon: "test",
24
26
  entityType: "Test",
25
- [DECLARABLE_MARKER]: true,
27
+ [DECLARABLE_MARKER]: true as const,
26
28
  prop1: "value",
27
29
  prop2: 123,
28
30
  };
@@ -34,6 +36,7 @@ describe("getAttributes", () => {
34
36
  test("returns property names with AttrRef values", () => {
35
37
  const parent = {};
36
38
  const entity: Declarable & { arn: AttrRef; name: AttrRef } = {
39
+ lexicon: "test",
37
40
  entityType: "Test",
38
41
  [DECLARABLE_MARKER]: true,
39
42
  arn: new AttrRef(parent, "Arn"),
@@ -53,6 +56,7 @@ describe("getAttributes", () => {
53
56
  regularProp: string;
54
57
  numberProp: number;
55
58
  } = {
59
+ lexicon: "test",
56
60
  entityType: "Test",
57
61
  [DECLARABLE_MARKER]: true,
58
62
  arn: new AttrRef(parent, "Arn"),
@@ -71,6 +75,7 @@ describe("getAttributes", () => {
71
75
  second: AttrRef;
72
76
  third: AttrRef;
73
77
  } = {
78
+ lexicon: "test",
74
79
  entityType: "Test",
75
80
  [DECLARABLE_MARKER]: true,
76
81
  first: new AttrRef(parent, "First"),
@@ -92,6 +97,7 @@ describe("getAttributes", () => {
92
97
  object: object;
93
98
  anotherAttrRef: AttrRef;
94
99
  } = {
100
+ lexicon: "test",
95
101
  entityType: "Test",
96
102
  [DECLARABLE_MARKER]: true,
97
103
  attrRef: new AttrRef(parent, "Attr1"),
@@ -112,6 +118,7 @@ describe("getAttributes", () => {
112
118
  describe("getLogicalName", () => {
113
119
  test("returns logical name when set", () => {
114
120
  const entity: Declarable & Record<symbol, unknown> = {
121
+ lexicon: "test",
115
122
  entityType: "Test",
116
123
  [DECLARABLE_MARKER]: true,
117
124
  [LOGICAL_NAME_SYMBOL]: "MyResource",
@@ -123,6 +130,7 @@ describe("getLogicalName", () => {
123
130
 
124
131
  test("throws when logical name is not set", () => {
125
132
  const entity: Declarable = {
133
+ lexicon: "test",
126
134
  entityType: "TestEntity",
127
135
  [DECLARABLE_MARKER]: true,
128
136
  };
@@ -134,6 +142,7 @@ describe("getLogicalName", () => {
134
142
 
135
143
  test("throws when logical name is not a string", () => {
136
144
  const entity: Declarable & Record<symbol, unknown> = {
145
+ lexicon: "test",
137
146
  entityType: "TestEntity",
138
147
  [DECLARABLE_MARKER]: true,
139
148
  [LOGICAL_NAME_SYMBOL]: 123,
@@ -149,6 +158,7 @@ describe("getLogicalName", () => {
149
158
 
150
159
  for (const name of names) {
151
160
  const entity: Declarable & Record<symbol, unknown> = {
161
+ lexicon: "test",
152
162
  entityType: "Test",
153
163
  [DECLARABLE_MARKER]: true,
154
164
  [LOGICAL_NAME_SYMBOL]: name,
@@ -160,6 +170,7 @@ describe("getLogicalName", () => {
160
170
 
161
171
  test("includes entity type in error message", () => {
162
172
  const entity: Declarable = {
173
+ lexicon: "test",
163
174
  entityType: "MyCustomType",
164
175
  [DECLARABLE_MARKER]: true,
165
176
  };
@@ -171,6 +182,7 @@ describe("getLogicalName", () => {
171
182
 
172
183
  test("throws when logical name is undefined", () => {
173
184
  const entity: Declarable & Record<symbol, unknown> = {
185
+ lexicon: "test",
174
186
  entityType: "TestEntity",
175
187
  [DECLARABLE_MARKER]: true,
176
188
  [LOGICAL_NAME_SYMBOL]: undefined,
@@ -183,6 +195,7 @@ describe("getLogicalName", () => {
183
195
 
184
196
  test("throws when logical name is null", () => {
185
197
  const entity: Declarable & Record<symbol, unknown> = {
198
+ lexicon: "test",
186
199
  entityType: "TestEntity",
187
200
  [DECLARABLE_MARKER]: true,
188
201
  [LOGICAL_NAME_SYMBOL]: null,
package/src/utils.ts CHANGED
@@ -6,6 +6,36 @@ import { AttrRef } from "./attrref";
6
6
  */
7
7
  export const LOGICAL_NAME_SYMBOL = Symbol.for("chant.logicalName");
8
8
 
9
+ /**
10
+ * Duck-type check for AttrRef that survives the dual-package hazard.
11
+ * When npm installs separate copies of @intentius/chant (one for the CLI,
12
+ * one for the lexicon), `instanceof AttrRef` fails across package boundaries.
13
+ */
14
+ export function isAttrRefLike(value: unknown): value is AttrRef {
15
+ if (value instanceof AttrRef) return true;
16
+ return (
17
+ typeof value === "object" &&
18
+ value !== null &&
19
+ "parent" in value &&
20
+ "attribute" in value &&
21
+ "_setLogicalName" in value &&
22
+ typeof (value as any).parent === "object" &&
23
+ typeof (value as any).attribute === "string"
24
+ );
25
+ }
26
+
27
+ /**
28
+ * JSON.stringify replacer that sorts object keys for deterministic output.
29
+ */
30
+ export function sortedJsonReplacer(_key: string, value: unknown): unknown {
31
+ if (value && typeof value === "object" && !Array.isArray(value)) {
32
+ return Object.fromEntries(
33
+ Object.entries(value as Record<string, unknown>).sort(([a], [b]) => a.localeCompare(b))
34
+ );
35
+ }
36
+ return value;
37
+ }
38
+
9
39
  /**
10
40
  * Get all property names that have AttrRef values
11
41
  * @param entity - The declarable entity to inspect
@@ -18,7 +48,7 @@ export function getAttributes(entity: Declarable): string[] {
18
48
  for (const key in obj) {
19
49
  if (Object.prototype.hasOwnProperty.call(obj, key)) {
20
50
  const value = obj[key];
21
- if (value instanceof AttrRef) {
51
+ if (isAttrRefLike(value)) {
22
52
  attributes.push(key);
23
53
  }
24
54
  }
@@ -50,6 +50,7 @@ describe("ValidationRule", () => {
50
50
 
51
51
  test("validate function receives entity and returns result", () => {
52
52
  const entity: Declarable = {
53
+ lexicon: "test",
53
54
  entityType: "Test",
54
55
  [DECLARABLE_MARKER]: true,
55
56
  };
@@ -71,6 +72,7 @@ describe("ValidationRule", () => {
71
72
  describe("validate", () => {
72
73
  test("returns empty array when no rules provided", () => {
73
74
  const entity: Declarable = {
75
+ lexicon: "test",
74
76
  entityType: "Test",
75
77
  [DECLARABLE_MARKER]: true,
76
78
  };
@@ -81,6 +83,7 @@ describe("validate", () => {
81
83
 
82
84
  test("applies single rule and returns result", () => {
83
85
  const entity: Declarable = {
86
+ lexicon: "test",
84
87
  entityType: "Test",
85
88
  [DECLARABLE_MARKER]: true,
86
89
  };
@@ -98,6 +101,7 @@ describe("validate", () => {
98
101
 
99
102
  test("applies multiple rules and returns all results", () => {
100
103
  const entity: Declarable = {
104
+ lexicon: "test",
101
105
  entityType: "Test",
102
106
  [DECLARABLE_MARKER]: true,
103
107
  };
@@ -130,6 +134,7 @@ describe("validate", () => {
130
134
 
131
135
  test("is non-blocking - does not throw on validation failure", () => {
132
136
  const entity: Declarable = {
137
+ lexicon: "test",
133
138
  entityType: "Test",
134
139
  [DECLARABLE_MARKER]: true,
135
140
  };
@@ -149,6 +154,7 @@ describe("validate", () => {
149
154
 
150
155
  test("passes entity to each rule", () => {
151
156
  const entity: Declarable & { name: string } = {
157
+ lexicon: "test",
152
158
  entityType: "Test",
153
159
  [DECLARABLE_MARKER]: true,
154
160
  name: "MyEntity",
@@ -172,6 +178,7 @@ describe("validate", () => {
172
178
 
173
179
  test("preserves rule execution order", () => {
174
180
  const entity: Declarable = {
181
+ lexicon: "test",
175
182
  entityType: "Test",
176
183
  [DECLARABLE_MARKER]: true,
177
184
  };
@@ -211,6 +218,7 @@ describe("validate", () => {
211
218
 
212
219
  test("handles rules with context in results", () => {
213
220
  const entity: Declarable & { count: number } = {
221
+ lexicon: "test",
214
222
  entityType: "Test",
215
223
  [DECLARABLE_MARKER]: true,
216
224
  count: 5,
@@ -240,6 +248,7 @@ describe("validate", () => {
240
248
 
241
249
  test("handles entity type validation", () => {
242
250
  const entity: Declarable = {
251
+ lexicon: "test",
243
252
  entityType: "Bucket",
244
253
  [DECLARABLE_MARKER]: true,
245
254
  };
@@ -263,6 +272,7 @@ describe("validate", () => {
263
272
 
264
273
  test("validation is opt-in - only runs rules provided", () => {
265
274
  const entity: Declarable = {
275
+ lexicon: "test",
266
276
  entityType: "Test",
267
277
  [DECLARABLE_MARKER]: true,
268
278
  };
@@ -274,6 +284,7 @@ describe("validate", () => {
274
284
 
275
285
  test("returns results in same order as rules", () => {
276
286
  const entity: Declarable = {
287
+ lexicon: "test",
277
288
  entityType: "Test",
278
289
  [DECLARABLE_MARKER]: true,
279
290
  };
@@ -1,6 +0,0 @@
1
- ---
2
- title: Getting Started
3
- description: Get started with the Fixture lexicon
4
- ---
5
-
6
- TODO: Document how to set up a project using the Fixture lexicon.
@@ -1,6 +0,0 @@
1
- ---
2
- title: Lint Rules
3
- description: Fixture lint rules reference
4
- ---
5
-
6
- TODO: Document the lint rules provided by the Fixture lexicon.
@@ -1,6 +0,0 @@
1
- ---
2
- title: Serialization
3
- description: Fixture output format
4
- ---
5
-
6
- TODO: Document the Fixture serialization format and output structure.
@@ -1,11 +0,0 @@
1
- /**
2
- * Coverage analysis for the fixture lexicon.
3
- *
4
- * TODO: Implement coverage analysis that checks how much of the
5
- * upstream spec is covered by the generated types.
6
- */
7
- export async function analyzeCoverage(options?: { verbose?: boolean }): Promise<void> {
8
- console.error("Coverage analysis not yet implemented");
9
- // TODO: Read generated lexicon JSON, compare against upstream spec,
10
- // and report coverage metrics.
11
- }
@@ -1,10 +0,0 @@
1
- import type { TypeScriptGenerator } from "@intentius/chant/import/generator";
2
-
3
- /**
4
- * TypeScript generator for converting imported fixture templates.
5
- *
6
- * TODO: Implement the TypeScriptGenerator interface for your format.
7
- */
8
- // export class FixtureGenerator implements TypeScriptGenerator {
9
- // generate(ir: IR): string { ... }
10
- // }
@@ -1,10 +0,0 @@
1
- import type { TemplateParser } from "@intentius/chant/import/parser";
2
-
3
- /**
4
- * Template parser for importing external fixture templates.
5
- *
6
- * TODO: Implement the TemplateParser interface for your format.
7
- */
8
- // export class FixtureParser implements TemplateParser {
9
- // parse(data: unknown): IR { ... }
10
- // }