@intentius/chant 0.0.4 → 0.0.8
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 +10 -351
- package/bin/chant +20 -0
- package/package.json +18 -17
- package/src/bench.test.ts +3 -54
- package/src/cli/commands/__fixtures__/init-lexicon-output/src/plugin.ts +8 -23
- package/src/cli/commands/__fixtures__/init-lexicon-output/src/validate.ts +22 -18
- package/src/cli/commands/__snapshots__/init-lexicon.test.ts.snap +8 -23
- package/src/cli/commands/build.ts +1 -2
- package/src/cli/commands/import.test.ts +1 -1
- package/src/cli/commands/import.ts +2 -2
- package/src/cli/commands/init-lexicon.test.ts +0 -3
- package/src/cli/commands/init-lexicon.ts +31 -95
- package/src/cli/commands/init.test.ts +10 -14
- package/src/cli/commands/init.ts +16 -10
- package/src/cli/commands/lint.ts +9 -33
- package/src/cli/commands/list.ts +2 -2
- package/src/cli/commands/update.ts +5 -3
- package/src/cli/conflict-check.test.ts +0 -1
- package/src/cli/handlers/dev.ts +1 -9
- package/src/cli/main.ts +14 -4
- package/src/cli/mcp/server.test.ts +207 -4
- package/src/cli/mcp/server.ts +6 -0
- package/src/cli/mcp/tools/explain.ts +134 -0
- package/src/cli/mcp/tools/scaffold.ts +107 -0
- package/src/cli/mcp/tools/search.ts +98 -0
- package/src/codegen/docs-interpolation.test.ts +2 -2
- package/src/codegen/docs.ts +5 -4
- package/src/codegen/generate-registry.test.ts +2 -2
- package/src/codegen/generate-registry.ts +5 -6
- package/src/codegen/generate-typescript.test.ts +6 -6
- package/src/codegen/generate-typescript.ts +2 -6
- package/src/codegen/generate.ts +1 -12
- package/src/codegen/package.ts +28 -1
- package/src/codegen/typecheck.ts +6 -11
- package/src/codegen/validate.ts +16 -0
- package/src/config.ts +4 -0
- package/src/discovery/files.ts +6 -6
- package/src/discovery/import.ts +1 -1
- package/src/index.ts +1 -2
- package/src/lexicon-integrity.ts +5 -4
- package/src/lexicon.ts +2 -6
- package/src/lint/config.ts +8 -6
- package/src/lint/engine.ts +1 -5
- package/src/lint/rule.ts +0 -18
- package/src/lint/rules/evl009-composite-no-constant.test.ts +24 -8
- package/src/lint/rules/evl009-composite-no-constant.ts +50 -29
- package/src/lint/rules/index.ts +1 -22
- package/src/runtime-adapter.ts +158 -0
- package/src/serializer-walker.test.ts +0 -9
- package/src/serializer-walker.ts +1 -3
- package/src/stack-output.ts +3 -3
- package/src/barrel.test.ts +0 -157
- package/src/barrel.ts +0 -101
- package/src/cli/commands/__fixtures__/init-lexicon-output/src/codegen/rollback.ts +0 -45
- package/src/codegen/case.test.ts +0 -30
- package/src/codegen/case.ts +0 -11
- package/src/codegen/rollback.test.ts +0 -92
- package/src/codegen/rollback.ts +0 -115
- package/src/lint/rules/barrel-import-style.test.ts +0 -80
- package/src/lint/rules/barrel-import-style.ts +0 -59
- package/src/lint/rules/enforce-barrel-import.test.ts +0 -169
- package/src/lint/rules/enforce-barrel-import.ts +0 -81
- package/src/lint/rules/enforce-barrel-ref.test.ts +0 -114
- package/src/lint/rules/enforce-barrel-ref.ts +0 -75
- package/src/lint/rules/evl006-barrel-usage.test.ts +0 -63
- package/src/lint/rules/evl006-barrel-usage.ts +0 -95
- package/src/lint/rules/evl008-unresolvable-barrel-ref.test.ts +0 -118
- package/src/lint/rules/evl008-unresolvable-barrel-ref.ts +0 -140
- package/src/lint/rules/prefer-namespace-import.test.ts +0 -102
- package/src/lint/rules/prefer-namespace-import.ts +0 -63
- package/src/lint/rules/stale-barrel-types.ts +0 -60
- package/src/project/scan.test.ts +0 -178
- package/src/project/scan.ts +0 -182
- package/src/project/sync.test.ts +0 -87
- package/src/project/sync.ts +0 -46
package/README.md
CHANGED
|
@@ -1,364 +1,23 @@
|
|
|
1
1
|
# @intentius/chant
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Core package for [chant](https://intentius.io/chant/) — a type system for operations.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
This package provides the lexicon-agnostic foundation that all chant lexicons build on. It includes the type system (Declarables, Intrinsics, Parameters, Outputs), the discovery and build pipeline, the semantic lint engine, the CLI, template import, and reusable codegen infrastructure for lexicon authors (runtime factories, naming strategies, generation and packaging pipelines, LSP providers).
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
Install it alongside a lexicon to start declaring infrastructure as typed TypeScript.
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
- **Type system**: Declarables, Intrinsics, Parameters, and Outputs
|
|
12
|
-
- **Discovery system**: File scanning, module loading, and entity collection
|
|
13
|
-
- **Build pipeline**: Dependency resolution, topological sorting, and serialization
|
|
14
|
-
- **Error handling**: Structured errors for discovery, build, and lint phases
|
|
15
|
-
- **Lint system**: Infrastructure code validation framework
|
|
16
|
-
- **Template import**: Convert external templates to TypeScript
|
|
17
|
-
- **Codegen infrastructure**: Reusable pipelines for generating, naming, packaging, and fetching schemas
|
|
18
|
-
- **LSP providers**: Generic lexicon-based completion and hover helpers
|
|
19
|
-
- **Runtime factories**: `createResource` and `createProperty` for Declarable-marked constructors
|
|
20
|
-
|
|
21
|
-
## Key Concepts
|
|
22
|
-
|
|
23
|
-
### Declarables
|
|
24
|
-
|
|
25
|
-
A `Declarable` is any entity that can be declared in an infrastructure specification:
|
|
26
|
-
|
|
27
|
-
```typescript
|
|
28
|
-
import { isDeclarable, DECLARABLE_MARKER } from "@intentius/chant";
|
|
29
|
-
|
|
30
|
-
if (isDeclarable(value)) {
|
|
31
|
-
console.log(value.entityType);
|
|
32
|
-
}
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
### Intrinsics
|
|
36
|
-
|
|
37
|
-
An `Intrinsic` represents a lexicon-provided function resolved at build time:
|
|
38
|
-
|
|
39
|
-
```typescript
|
|
40
|
-
import { isIntrinsic, INTRINSIC_MARKER } from "@intentius/chant";
|
|
41
|
-
|
|
42
|
-
if (isIntrinsic(value)) {
|
|
43
|
-
const serialized = value.toJSON();
|
|
44
|
-
}
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
### AttrRef
|
|
48
|
-
|
|
49
|
-
Reference attributes of other entities with deferred resolution:
|
|
50
|
-
|
|
51
|
-
```typescript
|
|
52
|
-
import { AttrRef } from "@intentius/chant";
|
|
53
|
-
|
|
54
|
-
const bucket = {};
|
|
55
|
-
const arnRef = new AttrRef(bucket, "arn");
|
|
56
|
-
|
|
57
|
-
// Later, during discovery
|
|
58
|
-
arnRef._setLogicalName("MyBucket");
|
|
59
|
-
arnRef.toJSON(); // { "Fn::GetAttr": ["MyBucket", "arn"] }
|
|
60
|
-
```
|
|
61
|
-
|
|
62
|
-
## Discovery System
|
|
63
|
-
|
|
64
|
-
Discover and collect infrastructure entities from TypeScript files:
|
|
65
|
-
|
|
66
|
-
```typescript
|
|
67
|
-
import { discover } from "@intentius/chant";
|
|
68
|
-
|
|
69
|
-
const result = await discover("./src/infra");
|
|
70
|
-
// result.entities: Map of entity name to Declarable
|
|
71
|
-
// result.dependencies: Dependency graph
|
|
72
|
-
// result.sourceFiles: Discovered files
|
|
73
|
-
// result.errors: Any errors encountered
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
### Individual Discovery Functions
|
|
77
|
-
|
|
78
|
-
```typescript
|
|
79
|
-
import {
|
|
80
|
-
findInfraFiles,
|
|
81
|
-
importModule,
|
|
82
|
-
collectEntities,
|
|
83
|
-
resolveAttrRefs,
|
|
84
|
-
buildDependencyGraph,
|
|
85
|
-
detectCycles,
|
|
86
|
-
topologicalSort,
|
|
87
|
-
} from "@intentius/chant";
|
|
88
|
-
|
|
89
|
-
// Find all .ts files (excluding tests and node_modules)
|
|
90
|
-
const files = await findInfraFiles("./src");
|
|
91
|
-
|
|
92
|
-
// Import a module
|
|
93
|
-
const exports = await importModule("./src/resources.ts");
|
|
94
|
-
|
|
95
|
-
// Collect declarables from modules
|
|
96
|
-
const entities = collectEntities([
|
|
97
|
-
{ file: "resources.ts", exports }
|
|
98
|
-
]);
|
|
99
|
-
|
|
100
|
-
// Resolve attribute references
|
|
101
|
-
resolveAttrRefs(entities);
|
|
102
|
-
|
|
103
|
-
// Build dependency graph
|
|
104
|
-
const deps = buildDependencyGraph(entities);
|
|
105
|
-
|
|
106
|
-
// Check for cycles
|
|
107
|
-
const cycles = detectCycles(deps);
|
|
108
|
-
|
|
109
|
-
// Topological sort
|
|
110
|
-
const order = topologicalSort(deps);
|
|
111
|
-
```
|
|
112
|
-
|
|
113
|
-
## Build Pipeline
|
|
114
|
-
|
|
115
|
-
Build infrastructure specifications with lexicon-specific serialization:
|
|
116
|
-
|
|
117
|
-
```typescript
|
|
118
|
-
import { build } from "@intentius/chant";
|
|
119
|
-
import { myLexicon } from "@intentius/chant-lexicon-myplatform";
|
|
120
|
-
|
|
121
|
-
const result = await build("./src/infra", [myLexicon]);
|
|
122
|
-
// result.outputs: Map of lexicon name to serialized output
|
|
123
|
-
// result.entities: Discovered entities
|
|
124
|
-
// result.warnings: Build warnings
|
|
125
|
-
// result.errors: Any errors
|
|
126
|
-
```
|
|
127
|
-
|
|
128
|
-
## Error Handling
|
|
129
|
-
|
|
130
|
-
Structured error types for different phases:
|
|
131
|
-
|
|
132
|
-
```typescript
|
|
133
|
-
import { DiscoveryError, BuildError, LintError } from "@intentius/chant";
|
|
134
|
-
|
|
135
|
-
// Discovery phase errors
|
|
136
|
-
throw new DiscoveryError("config.ts", "Module not found", "import");
|
|
137
|
-
|
|
138
|
-
// Build phase errors
|
|
139
|
-
throw new BuildError("MyResource", "Invalid configuration");
|
|
140
|
-
|
|
141
|
-
// Lint errors with location
|
|
142
|
-
const error = new LintError(
|
|
143
|
-
"config.ts",
|
|
144
|
-
10,
|
|
145
|
-
5,
|
|
146
|
-
"no-unused",
|
|
147
|
-
"Variable is declared but never used"
|
|
148
|
-
);
|
|
149
|
-
|
|
150
|
-
// All errors support JSON serialization
|
|
151
|
-
const json = error.toJSON();
|
|
152
|
-
```
|
|
153
|
-
|
|
154
|
-
## Lint System
|
|
155
|
-
|
|
156
|
-
Validate infrastructure code with custom rules:
|
|
157
|
-
|
|
158
|
-
```typescript
|
|
159
|
-
import { parseFile } from "@intentius/chant";
|
|
160
|
-
import type { LintRule, LintContext } from "@intentius/chant";
|
|
161
|
-
|
|
162
|
-
// Parse a file for linting
|
|
163
|
-
const sourceFile = parseFile("./src/infra/main.ts");
|
|
164
|
-
|
|
165
|
-
// Define a lint rule
|
|
166
|
-
const myRule: LintRule = {
|
|
167
|
-
id: "my-rule",
|
|
168
|
-
severity: "error",
|
|
169
|
-
category: "correctness",
|
|
170
|
-
check(context: LintContext): LintDiagnostic[] {
|
|
171
|
-
// Analyze context.sourceFile
|
|
172
|
-
return [];
|
|
173
|
-
},
|
|
174
|
-
fix(context: LintContext): LintFix[] {
|
|
175
|
-
// Optional: provide auto-fixes
|
|
176
|
-
return [];
|
|
177
|
-
}
|
|
178
|
-
};
|
|
179
|
-
```
|
|
180
|
-
|
|
181
|
-
## Serializer Interface
|
|
182
|
-
|
|
183
|
-
Implement lexicon-specific serialization:
|
|
184
|
-
|
|
185
|
-
```typescript
|
|
186
|
-
import type { Serializer, Declarable } from "@intentius/chant";
|
|
187
|
-
|
|
188
|
-
const mySerializer: Serializer = {
|
|
189
|
-
name: "my-lexicon",
|
|
190
|
-
rulePrefix: "ML",
|
|
191
|
-
serialize(entities: Map<string, Declarable>): string {
|
|
192
|
-
// Serialize entities to lexicon-specific format
|
|
193
|
-
return JSON.stringify({ entities: Array.from(entities.keys()) });
|
|
194
|
-
}
|
|
195
|
-
};
|
|
196
|
-
```
|
|
197
|
-
|
|
198
|
-
## Utilities
|
|
199
|
-
|
|
200
|
-
Helper functions for working with declarables:
|
|
201
|
-
|
|
202
|
-
```typescript
|
|
203
|
-
import {
|
|
204
|
-
getAttributes,
|
|
205
|
-
getLogicalName,
|
|
206
|
-
LOGICAL_NAME_SYMBOL
|
|
207
|
-
} from "@intentius/chant";
|
|
208
|
-
|
|
209
|
-
// Get attribute names that have AttrRef values
|
|
210
|
-
const attrs = getAttributes(myEntity);
|
|
211
|
-
// ["arn", "endpoint"]
|
|
212
|
-
|
|
213
|
-
// Get the logical name assigned during discovery
|
|
214
|
-
(entity as any)[LOGICAL_NAME_SYMBOL] = "MyResource";
|
|
215
|
-
const name = getLogicalName(entity);
|
|
216
|
-
// "MyResource"
|
|
217
|
-
```
|
|
218
|
-
|
|
219
|
-
## Lexicon Detection
|
|
220
|
-
|
|
221
|
-
Automatically detect which lexicon is being used:
|
|
222
|
-
|
|
223
|
-
```typescript
|
|
224
|
-
import { detectLexicon } from "@intentius/chant";
|
|
225
|
-
|
|
226
|
-
const lexicon = await detectLexicon(["./src/infra/main.ts"]);
|
|
227
|
-
// "aws" (currently the only supported lexicon)
|
|
228
|
-
```
|
|
229
|
-
|
|
230
|
-
## Template Import System
|
|
231
|
-
|
|
232
|
-
Convert external templates to TypeScript:
|
|
233
|
-
|
|
234
|
-
```typescript
|
|
235
|
-
import type {
|
|
236
|
-
TemplateIR,
|
|
237
|
-
TemplateParser,
|
|
238
|
-
TypeScriptGenerator
|
|
239
|
-
} from "@intentius/chant";
|
|
240
|
-
|
|
241
|
-
// Parser converts external format to IR
|
|
242
|
-
const parser: TemplateParser = {
|
|
243
|
-
parse(content: string): TemplateIR {
|
|
244
|
-
return { resources: [], parameters: [] };
|
|
245
|
-
}
|
|
246
|
-
};
|
|
247
|
-
|
|
248
|
-
// Generator converts IR to TypeScript
|
|
249
|
-
const generator: TypeScriptGenerator = {
|
|
250
|
-
generate(ir: TemplateIR): GeneratedFile[] {
|
|
251
|
-
return [{ path: "resources.ts", content: "..." }];
|
|
252
|
-
}
|
|
253
|
-
};
|
|
254
|
-
```
|
|
255
|
-
|
|
256
|
-
## Codegen Infrastructure
|
|
257
|
-
|
|
258
|
-
Core provides reusable infrastructure for lexicon code generation pipelines. Lexicons supply provider-specific callbacks; core handles orchestration.
|
|
259
|
-
|
|
260
|
-
### Runtime Factories
|
|
261
|
-
|
|
262
|
-
Create Declarable-marked constructors for generated resource and property types:
|
|
263
|
-
|
|
264
|
-
```typescript
|
|
265
|
-
import { createResource, createProperty } from "@intentius/chant/runtime";
|
|
266
|
-
|
|
267
|
-
// Creates a constructor that stamps out Declarable objects
|
|
268
|
-
const MyResource = createResource("Provider::Service::Type", "my-lexicon", { arn: "Arn" });
|
|
269
|
-
const MyProperty = createProperty("Provider::Service::Type.PropType", "my-lexicon");
|
|
9
|
+
```bash
|
|
10
|
+
npm install --save-dev @intentius/chant @intentius/chant-lexicon-aws
|
|
270
11
|
```
|
|
271
12
|
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
Collision-free TypeScript class name generation, parameterized by data tables:
|
|
275
|
-
|
|
276
|
-
```typescript
|
|
277
|
-
import { NamingStrategy, type NamingConfig } from "@intentius/chant/codegen/naming";
|
|
278
|
-
|
|
279
|
-
const config: NamingConfig = {
|
|
280
|
-
priorityNames: { "Provider::S3::Bucket": "Bucket" },
|
|
281
|
-
priorityAliases: {},
|
|
282
|
-
priorityPropertyAliases: {},
|
|
283
|
-
serviceAbbreviations: { "ElasticLoadBalancingV2": "Elbv2" },
|
|
284
|
-
shortName: (t) => t.split("::").pop()!,
|
|
285
|
-
serviceName: (t) => t.split("::")[1],
|
|
286
|
-
};
|
|
287
|
-
|
|
288
|
-
const naming = new NamingStrategy(inputs, config);
|
|
289
|
-
naming.resolve("Provider::S3::Bucket"); // "Bucket"
|
|
290
|
-
```
|
|
291
|
-
|
|
292
|
-
### Generation Pipeline
|
|
293
|
-
|
|
294
|
-
Generic pipeline orchestration — step sequencing, logging, warning collection, stats counting:
|
|
295
|
-
|
|
296
|
-
```typescript
|
|
297
|
-
import { generatePipeline, type GeneratePipelineConfig } from "@intentius/chant/codegen/generate";
|
|
298
|
-
|
|
299
|
-
const config: GeneratePipelineConfig<MyParsedResult> = {
|
|
300
|
-
fetchSchemas: async (opts) => { /* ... */ },
|
|
301
|
-
parseSchema: (name, data) => { /* ... */ },
|
|
302
|
-
createNaming: (results) => new MyNamingStrategy(results),
|
|
303
|
-
generateRegistry: (results, naming) => { /* ... */ },
|
|
304
|
-
generateTypes: (results, naming) => { /* ... */ },
|
|
305
|
-
generateRuntimeIndex: (results, naming) => { /* ... */ },
|
|
306
|
-
};
|
|
307
|
-
|
|
308
|
-
const result = await generatePipeline(config, { verbose: true });
|
|
309
|
-
```
|
|
310
|
-
|
|
311
|
-
### Packaging Pipeline
|
|
312
|
-
|
|
313
|
-
Bundles generation output into a distributable `BundleSpec`:
|
|
314
|
-
|
|
315
|
-
```typescript
|
|
316
|
-
import { packagePipeline, type PackagePipelineConfig } from "@intentius/chant/codegen/package";
|
|
317
|
-
|
|
318
|
-
const result = await packagePipeline({
|
|
319
|
-
generate: (opts) => myGenerate(opts),
|
|
320
|
-
buildManifest: (genResult) => ({ name: "my-lexicon", version: "1.0.0", /* ... */ }),
|
|
321
|
-
srcDir: __dirname,
|
|
322
|
-
collectSkills: () => new Map(),
|
|
323
|
-
});
|
|
324
|
-
```
|
|
325
|
-
|
|
326
|
-
### Fetch Utilities
|
|
327
|
-
|
|
328
|
-
HTTP fetch with local file caching and zip extraction:
|
|
329
|
-
|
|
330
|
-
```typescript
|
|
331
|
-
import { fetchWithCache, extractFromZip } from "@intentius/chant/codegen/fetch";
|
|
332
|
-
|
|
333
|
-
const data = await fetchWithCache({ url: "https://...", cacheFile: "/tmp/cache.zip" });
|
|
334
|
-
const files = await extractFromZip(data, (name) => name.endsWith(".json"));
|
|
335
|
-
```
|
|
336
|
-
|
|
337
|
-
### LSP Providers
|
|
338
|
-
|
|
339
|
-
Generic lexicon-based completion and hover:
|
|
340
|
-
|
|
341
|
-
```typescript
|
|
342
|
-
import { LexiconIndex, lexiconCompletions, lexiconHover } from "@intentius/chant/lsp/lexicon-providers";
|
|
343
|
-
|
|
344
|
-
const index = new LexiconIndex(lexiconData);
|
|
345
|
-
const completions = lexiconCompletions(ctx, index, "My resource");
|
|
346
|
-
const hover = lexiconHover(ctx, index);
|
|
347
|
-
```
|
|
348
|
-
|
|
349
|
-
## TypeScript Support
|
|
350
|
-
|
|
351
|
-
This package is written in TypeScript and provides full type definitions.
|
|
352
|
-
|
|
353
|
-
## Documentation
|
|
354
|
-
|
|
355
|
-
- [Core Concepts](../../docs/src/content/docs/guides/core-concepts.md) - Detailed guide on declarables, intrinsics, and the type system
|
|
356
|
-
- [Testing Guide](../../TESTING.md) - Testing patterns and utilities
|
|
13
|
+
**[Documentation →](https://intentius.io/chant/getting-started/introduction/)**
|
|
357
14
|
|
|
358
15
|
## Related Packages
|
|
359
16
|
|
|
360
|
-
|
|
361
|
-
|
|
17
|
+
| Package | Role |
|
|
18
|
+
|---------|------|
|
|
19
|
+
| [@intentius/chant-lexicon-aws](https://www.npmjs.com/package/@intentius/chant-lexicon-aws) | AWS CloudFormation lexicon |
|
|
20
|
+
| [@intentius/chant-lexicon-gitlab](https://www.npmjs.com/package/@intentius/chant-lexicon-gitlab) | GitLab CI lexicon |
|
|
362
21
|
|
|
363
22
|
## License
|
|
364
23
|
|
package/bin/chant
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
# Cross-runtime CLI wrapper. Tries bun first, falls back to npx tsx.
|
|
3
|
+
set -e
|
|
4
|
+
|
|
5
|
+
# Resolve symlinks to find the real script location
|
|
6
|
+
SELF="$0"
|
|
7
|
+
while [ -L "$SELF" ]; do
|
|
8
|
+
DIR="$(cd "$(dirname "$SELF")" && pwd)"
|
|
9
|
+
SELF="$(readlink "$SELF")"
|
|
10
|
+
# Handle relative symlink targets
|
|
11
|
+
case "$SELF" in /*) ;; *) SELF="$DIR/$SELF" ;; esac
|
|
12
|
+
done
|
|
13
|
+
SCRIPT_DIR="$(cd "$(dirname "$SELF")" && pwd)"
|
|
14
|
+
MAIN_TS="$SCRIPT_DIR/../src/cli/main.ts"
|
|
15
|
+
|
|
16
|
+
if command -v bun >/dev/null 2>&1; then
|
|
17
|
+
exec bun "$MAIN_TS" "$@"
|
|
18
|
+
else
|
|
19
|
+
exec npx tsx "$MAIN_TS" "$@"
|
|
20
|
+
fi
|
package/package.json
CHANGED
|
@@ -1,23 +1,24 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@intentius/chant",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.8",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"type": "module",
|
|
6
|
-
"files": ["src/"],
|
|
6
|
+
"files": ["src/", "bin/"],
|
|
7
7
|
"publishConfig": {
|
|
8
|
-
|
|
9
|
-
},
|
|
10
|
-
"bin": {
|
|
11
|
-
|
|
12
|
-
},
|
|
13
|
-
"exports": {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
},
|
|
19
|
-
"dependencies": {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
8
|
+
"access": "public"
|
|
9
|
+
},
|
|
10
|
+
"bin": {
|
|
11
|
+
"chant": "./bin/chant"
|
|
12
|
+
},
|
|
13
|
+
"exports": {
|
|
14
|
+
".": "./src/index.ts",
|
|
15
|
+
"./cli": "./src/cli/index.ts",
|
|
16
|
+
"./cli/*": "./src/cli/*",
|
|
17
|
+
"./*": "./src/*"
|
|
18
|
+
},
|
|
19
|
+
"dependencies": {
|
|
20
|
+
"fflate": "^0.8.2",
|
|
21
|
+
"picomatch": "^4.0.3",
|
|
22
|
+
"zod": "^4.3.6"
|
|
23
|
+
}
|
|
23
24
|
}
|
package/src/bench.test.ts
CHANGED
|
@@ -6,60 +6,9 @@ import { discover } from "./discovery/index";
|
|
|
6
6
|
import { runLint } from "./lint/engine";
|
|
7
7
|
import { build } from "./build";
|
|
8
8
|
import type { Serializer } from "./serializer";
|
|
9
|
-
import
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
import {
|
|
13
|
-
flatDeclarationsRule,
|
|
14
|
-
exportRequiredRule,
|
|
15
|
-
fileDeclarableLimitRule,
|
|
16
|
-
singleConcernFileRule,
|
|
17
|
-
preferNamespaceImportRule,
|
|
18
|
-
barrelImportStyleRule,
|
|
19
|
-
declarableNamingConventionRule,
|
|
20
|
-
noUnusedDeclarableImportRule,
|
|
21
|
-
noRedundantValueCastRule,
|
|
22
|
-
noUnusedDeclarableRule,
|
|
23
|
-
noCyclicDeclarableRefRule,
|
|
24
|
-
noRedundantTypeImportRule,
|
|
25
|
-
noStringRefRule,
|
|
26
|
-
enforceBarrelImportRule,
|
|
27
|
-
enforceBarrelRefRule,
|
|
28
|
-
evl001NonLiteralExpressionRule,
|
|
29
|
-
evl002ControlFlowResourceRule,
|
|
30
|
-
evl003DynamicPropertyAccessRule,
|
|
31
|
-
evl004SpreadNonConstRule,
|
|
32
|
-
evl005ResourceBlockBodyRule,
|
|
33
|
-
evl006BarrelUsageRule,
|
|
34
|
-
evl007InvalidSiblingsRule,
|
|
35
|
-
evl008UnresolvableBarrelRefRule,
|
|
36
|
-
} from "./lint/rules/index";
|
|
37
|
-
|
|
38
|
-
const coreRules: LintRule[] = [
|
|
39
|
-
flatDeclarationsRule,
|
|
40
|
-
exportRequiredRule,
|
|
41
|
-
fileDeclarableLimitRule,
|
|
42
|
-
singleConcernFileRule,
|
|
43
|
-
preferNamespaceImportRule,
|
|
44
|
-
barrelImportStyleRule,
|
|
45
|
-
declarableNamingConventionRule,
|
|
46
|
-
noUnusedDeclarableImportRule,
|
|
47
|
-
noRedundantValueCastRule,
|
|
48
|
-
noUnusedDeclarableRule,
|
|
49
|
-
noCyclicDeclarableRefRule,
|
|
50
|
-
noRedundantTypeImportRule,
|
|
51
|
-
noStringRefRule,
|
|
52
|
-
enforceBarrelImportRule,
|
|
53
|
-
enforceBarrelRefRule,
|
|
54
|
-
evl001NonLiteralExpressionRule,
|
|
55
|
-
evl002ControlFlowResourceRule,
|
|
56
|
-
evl003DynamicPropertyAccessRule,
|
|
57
|
-
evl004SpreadNonConstRule,
|
|
58
|
-
evl005ResourceBlockBodyRule,
|
|
59
|
-
evl006BarrelUsageRule,
|
|
60
|
-
evl007InvalidSiblingsRule,
|
|
61
|
-
evl008UnresolvableBarrelRefRule,
|
|
62
|
-
];
|
|
9
|
+
import { loadCoreRules } from "./lint/rules/index";
|
|
10
|
+
|
|
11
|
+
const coreRules = loadCoreRules();
|
|
63
12
|
|
|
64
13
|
interface FixtureSize {
|
|
65
14
|
name: string;
|
|
@@ -19,7 +19,9 @@ export const fixturePlugin: LexiconPlugin = {
|
|
|
19
19
|
|
|
20
20
|
async validate(options?: { verbose?: boolean }): Promise<void> {
|
|
21
21
|
const { validate } = await import("./validate");
|
|
22
|
-
await validate
|
|
22
|
+
const { printValidationResult } = await import("@intentius/chant/codegen/validate");
|
|
23
|
+
const result = await validate();
|
|
24
|
+
printValidationResult(result);
|
|
23
25
|
},
|
|
24
26
|
|
|
25
27
|
async coverage(options?: { verbose?: boolean; minOverall?: number }): Promise<void> {
|
|
@@ -29,32 +31,15 @@ export const fixturePlugin: LexiconPlugin = {
|
|
|
29
31
|
|
|
30
32
|
async package(options?: { verbose?: boolean; force?: boolean }): Promise<void> {
|
|
31
33
|
const { packageLexicon } = await import("./codegen/package");
|
|
32
|
-
await
|
|
33
|
-
},
|
|
34
|
-
|
|
35
|
-
async rollback(options?: { restore?: string; verbose?: boolean }): Promise<void> {
|
|
36
|
-
const { listSnapshots, restoreSnapshot } = await import("./codegen/rollback");
|
|
34
|
+
const { writeBundleSpec } = await import("@intentius/chant/codegen/package");
|
|
37
35
|
const { join, dirname } = await import("path");
|
|
38
36
|
const { fileURLToPath } = await import("url");
|
|
39
37
|
|
|
38
|
+
const { spec, stats } = await packageLexicon(options);
|
|
40
39
|
const pkgDir = dirname(dirname(fileURLToPath(import.meta.url)));
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
const generatedDir = join(pkgDir, "src", "generated");
|
|
45
|
-
restoreSnapshot(String(options.restore), generatedDir);
|
|
46
|
-
console.error(`Restored snapshot: ${options.restore}`);
|
|
47
|
-
} else {
|
|
48
|
-
const snapshots = listSnapshots(snapshotsDir);
|
|
49
|
-
if (snapshots.length === 0) {
|
|
50
|
-
console.error("No snapshots available.");
|
|
51
|
-
} else {
|
|
52
|
-
console.error(`Available snapshots (${snapshots.length}):`);
|
|
53
|
-
for (const s of snapshots) {
|
|
54
|
-
console.error(` ${s.timestamp} ${s.resources} resources ${s.path}`);
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
}
|
|
40
|
+
writeBundleSpec(spec, join(pkgDir, "dist"));
|
|
41
|
+
|
|
42
|
+
console.error(`Packaged ${stats.resources} resources, ${stats.ruleCount} rules, ${stats.skillCount} skills`);
|
|
58
43
|
},
|
|
59
44
|
|
|
60
45
|
// ── Optional extensions (uncomment and implement as needed) ───
|
|
@@ -1,24 +1,28 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Validate generated
|
|
2
|
+
* Validate generated lexicon-fixture artifacts.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* Thin wrapper around the core validation framework
|
|
5
|
+
* with fixture-specific configuration.
|
|
5
6
|
*/
|
|
6
|
-
export async function validate(options?: { verbose?: boolean }): Promise<void> {
|
|
7
|
-
const checks = [
|
|
8
|
-
// TODO: Add checks — e.g. verify lexicon JSON exists, types compile,
|
|
9
|
-
// registry has expected resources, etc.
|
|
10
|
-
{ name: "placeholder", ok: true, error: undefined as string | undefined },
|
|
11
|
-
];
|
|
12
7
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
console.error(` [${status}] ${check.name}${msg}`);
|
|
17
|
-
}
|
|
8
|
+
import { dirname } from "path";
|
|
9
|
+
import { fileURLToPath } from "url";
|
|
10
|
+
import { validateLexiconArtifacts, type ValidateResult } from "@intentius/chant/codegen/validate";
|
|
18
11
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
12
|
+
export type { ValidateCheck, ValidateResult } from "@intentius/chant/codegen/validate";
|
|
13
|
+
|
|
14
|
+
// TODO: Add names of required entities for your lexicon
|
|
15
|
+
const REQUIRED_NAMES: string[] = [];
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Validate the generated lexicon-fixture artifacts.
|
|
19
|
+
*/
|
|
20
|
+
export async function validate(opts?: { basePath?: string }): Promise<ValidateResult> {
|
|
21
|
+
const basePath = opts?.basePath ?? dirname(dirname(fileURLToPath(import.meta.url)));
|
|
22
|
+
|
|
23
|
+
return validateLexiconArtifacts({
|
|
24
|
+
lexiconJsonFilename: "lexicon-fixture.json",
|
|
25
|
+
requiredNames: REQUIRED_NAMES,
|
|
26
|
+
basePath,
|
|
27
|
+
});
|
|
24
28
|
}
|
|
@@ -129,7 +129,9 @@ export const fixturePlugin: LexiconPlugin = {
|
|
|
129
129
|
|
|
130
130
|
async validate(options?: { verbose?: boolean }): Promise<void> {
|
|
131
131
|
const { validate } = await import("./validate");
|
|
132
|
-
await validate
|
|
132
|
+
const { printValidationResult } = await import("@intentius/chant/codegen/validate");
|
|
133
|
+
const result = await validate();
|
|
134
|
+
printValidationResult(result);
|
|
133
135
|
},
|
|
134
136
|
|
|
135
137
|
async coverage(options?: { verbose?: boolean; minOverall?: number }): Promise<void> {
|
|
@@ -139,32 +141,15 @@ export const fixturePlugin: LexiconPlugin = {
|
|
|
139
141
|
|
|
140
142
|
async package(options?: { verbose?: boolean; force?: boolean }): Promise<void> {
|
|
141
143
|
const { packageLexicon } = await import("./codegen/package");
|
|
142
|
-
await
|
|
143
|
-
},
|
|
144
|
-
|
|
145
|
-
async rollback(options?: { restore?: string; verbose?: boolean }): Promise<void> {
|
|
146
|
-
const { listSnapshots, restoreSnapshot } = await import("./codegen/rollback");
|
|
144
|
+
const { writeBundleSpec } = await import("@intentius/chant/codegen/package");
|
|
147
145
|
const { join, dirname } = await import("path");
|
|
148
146
|
const { fileURLToPath } = await import("url");
|
|
149
147
|
|
|
148
|
+
const { spec, stats } = await packageLexicon(options);
|
|
150
149
|
const pkgDir = dirname(dirname(fileURLToPath(import.meta.url)));
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
const generatedDir = join(pkgDir, "src", "generated");
|
|
155
|
-
restoreSnapshot(String(options.restore), generatedDir);
|
|
156
|
-
console.error(\`Restored snapshot: \${options.restore}\`);
|
|
157
|
-
} else {
|
|
158
|
-
const snapshots = listSnapshots(snapshotsDir);
|
|
159
|
-
if (snapshots.length === 0) {
|
|
160
|
-
console.error("No snapshots available.");
|
|
161
|
-
} else {
|
|
162
|
-
console.error(\`Available snapshots (\${snapshots.length}):\`);
|
|
163
|
-
for (const s of snapshots) {
|
|
164
|
-
console.error(\` \${s.timestamp} \${s.resources} resources \${s.path}\`);
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
}
|
|
150
|
+
writeBundleSpec(spec, join(pkgDir, "dist"));
|
|
151
|
+
|
|
152
|
+
console.error(\`Packaged \${stats.resources} resources, \${stats.ruleCount} rules, \${stats.skillCount} skills\`);
|
|
168
153
|
},
|
|
169
154
|
|
|
170
155
|
// ── Optional extensions (uncomment and implement as needed) ───
|
|
@@ -5,7 +5,7 @@ import { runPostSynthChecks } from "../../lint/post-synth";
|
|
|
5
5
|
import type { PostSynthCheck } from "../../lint/post-synth";
|
|
6
6
|
import { formatError, formatWarning, formatSuccess, formatBold, formatInfo } from "../format";
|
|
7
7
|
import { writeFileSync } from "fs";
|
|
8
|
-
import { resolve } from "path";
|
|
8
|
+
import { resolve, dirname, join } from "path";
|
|
9
9
|
import { watchDirectory, formatTimestamp, formatChangedFiles } from "../watch";
|
|
10
10
|
|
|
11
11
|
/**
|
|
@@ -172,7 +172,6 @@ export async function buildCommand(options: BuildOptions): Promise<BuildResult>
|
|
|
172
172
|
|
|
173
173
|
// Write additional files (e.g. nested stack templates) alongside the primary output
|
|
174
174
|
if (additionalFiles.size > 0) {
|
|
175
|
-
const { dirname, join } = require("path");
|
|
176
175
|
const outputDir = dirname(outputPath);
|
|
177
176
|
for (const [filename, content] of additionalFiles) {
|
|
178
177
|
let fileContent = content;
|
|
@@ -52,7 +52,7 @@ describe("importCommand", () => {
|
|
|
52
52
|
expect(result.lexicon).toBe("aws");
|
|
53
53
|
expect(result.generatedFiles.length).toBeGreaterThan(0);
|
|
54
54
|
expect(existsSync(outputDir)).toBe(true);
|
|
55
|
-
});
|
|
55
|
+
}, 15000);
|
|
56
56
|
|
|
57
57
|
test("imports CloudFormation template with multiple resources", async () => {
|
|
58
58
|
const template = {
|