@intentius/chant 0.0.4 → 0.0.5
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/package.json +1 -1
- package/src/bench.test.ts +3 -54
- package/src/cli/commands/__fixtures__/init-lexicon-output/src/plugin.ts +12 -2
- package/src/cli/commands/__fixtures__/init-lexicon-output/src/validate.ts +22 -18
- package/src/cli/commands/__snapshots__/init-lexicon.test.ts.snap +12 -2
- package/src/cli/commands/import.test.ts +1 -1
- package/src/cli/commands/init-lexicon.ts +34 -20
- package/src/cli/commands/init.test.ts +10 -14
- package/src/cli/commands/init.ts +2 -7
- package/src/cli/commands/lint.ts +9 -33
- package/src/cli/main.ts +1 -1
- package/src/codegen/docs-interpolation.test.ts +2 -2
- package/src/codegen/docs.ts +5 -4
- package/src/codegen/generate-registry.test.ts +1 -1
- package/src/codegen/generate-registry.ts +3 -3
- package/src/codegen/package.ts +28 -1
- package/src/codegen/validate.ts +16 -0
- package/src/discovery/files.ts +6 -6
- package/src/discovery/import.ts +1 -1
- package/src/index.ts +0 -1
- 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/stack-output.ts +3 -3
- package/src/barrel.test.ts +0 -157
- package/src/barrel.ts +0 -101
- 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/package.json
CHANGED
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,7 +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
|
|
34
|
+
const { writeBundleSpec } = await import("@intentius/chant/codegen/package");
|
|
35
|
+
const { join, dirname } = await import("path");
|
|
36
|
+
const { fileURLToPath } = await import("url");
|
|
37
|
+
|
|
38
|
+
const { spec, stats } = await packageLexicon(options);
|
|
39
|
+
const pkgDir = dirname(dirname(fileURLToPath(import.meta.url)));
|
|
40
|
+
writeBundleSpec(spec, join(pkgDir, "dist"));
|
|
41
|
+
|
|
42
|
+
console.error(`Packaged ${stats.resources} resources, ${stats.ruleCount} rules, ${stats.skillCount} skills`);
|
|
33
43
|
},
|
|
34
44
|
|
|
35
45
|
async rollback(options?: { restore?: string; verbose?: boolean }): Promise<void> {
|
|
@@ -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,7 +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
|
|
144
|
+
const { writeBundleSpec } = await import("@intentius/chant/codegen/package");
|
|
145
|
+
const { join, dirname } = await import("path");
|
|
146
|
+
const { fileURLToPath } = await import("url");
|
|
147
|
+
|
|
148
|
+
const { spec, stats } = await packageLexicon(options);
|
|
149
|
+
const pkgDir = dirname(dirname(fileURLToPath(import.meta.url)));
|
|
150
|
+
writeBundleSpec(spec, join(pkgDir, "dist"));
|
|
151
|
+
|
|
152
|
+
console.error(\`Packaged \${stats.resources} resources, \${stats.ruleCount} rules, \${stats.skillCount} skills\`);
|
|
143
153
|
},
|
|
144
154
|
|
|
145
155
|
async rollback(options?: { restore?: string; verbose?: boolean }): Promise<void> {
|
|
@@ -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 = {
|
|
@@ -83,7 +83,9 @@ export const ${names.pluginVarName}: LexiconPlugin = {
|
|
|
83
83
|
|
|
84
84
|
async validate(options?: { verbose?: boolean }): Promise<void> {
|
|
85
85
|
const { validate } = await import("./validate");
|
|
86
|
-
await validate
|
|
86
|
+
const { printValidationResult } = await import("@intentius/chant/codegen/validate");
|
|
87
|
+
const result = await validate();
|
|
88
|
+
printValidationResult(result);
|
|
87
89
|
},
|
|
88
90
|
|
|
89
91
|
async coverage(options?: { verbose?: boolean; minOverall?: number }): Promise<void> {
|
|
@@ -93,7 +95,15 @@ export const ${names.pluginVarName}: LexiconPlugin = {
|
|
|
93
95
|
|
|
94
96
|
async package(options?: { verbose?: boolean; force?: boolean }): Promise<void> {
|
|
95
97
|
const { packageLexicon } = await import("./codegen/package");
|
|
96
|
-
await
|
|
98
|
+
const { writeBundleSpec } = await import("@intentius/chant/codegen/package");
|
|
99
|
+
const { join, dirname } = await import("path");
|
|
100
|
+
const { fileURLToPath } = await import("url");
|
|
101
|
+
|
|
102
|
+
const { spec, stats } = await packageLexicon(options);
|
|
103
|
+
const pkgDir = dirname(dirname(fileURLToPath(import.meta.url)));
|
|
104
|
+
writeBundleSpec(spec, join(pkgDir, "dist"));
|
|
105
|
+
|
|
106
|
+
console.error(\`Packaged \${stats.resources} resources, \${stats.ruleCount} rules, \${stats.skillCount} skills\`);
|
|
97
107
|
},
|
|
98
108
|
|
|
99
109
|
async rollback(options?: { restore?: string; verbose?: boolean }): Promise<void> {
|
|
@@ -612,28 +622,32 @@ export async function analyzeCoverage(options?: { verbose?: boolean }): Promise<
|
|
|
612
622
|
|
|
613
623
|
function generateValidateTs(name: string): string {
|
|
614
624
|
return `/**
|
|
615
|
-
* Validate generated
|
|
625
|
+
* Validate generated lexicon-${name} artifacts.
|
|
616
626
|
*
|
|
617
|
-
*
|
|
627
|
+
* Thin wrapper around the core validation framework
|
|
628
|
+
* with ${name}-specific configuration.
|
|
618
629
|
*/
|
|
619
|
-
export async function validate(options?: { verbose?: boolean }): Promise<void> {
|
|
620
|
-
const checks = [
|
|
621
|
-
// TODO: Add checks — e.g. verify lexicon JSON exists, types compile,
|
|
622
|
-
// registry has expected resources, etc.
|
|
623
|
-
{ name: "placeholder", ok: true, error: undefined as string | undefined },
|
|
624
|
-
];
|
|
625
630
|
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
console.error(\` [\${status}] \${check.name}\${msg}\`);
|
|
630
|
-
}
|
|
631
|
+
import { dirname } from "path";
|
|
632
|
+
import { fileURLToPath } from "url";
|
|
633
|
+
import { validateLexiconArtifacts, type ValidateResult } from "@intentius/chant/codegen/validate";
|
|
631
634
|
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
635
|
+
export type { ValidateCheck, ValidateResult } from "@intentius/chant/codegen/validate";
|
|
636
|
+
|
|
637
|
+
// TODO: Add names of required entities for your lexicon
|
|
638
|
+
const REQUIRED_NAMES: string[] = [];
|
|
639
|
+
|
|
640
|
+
/**
|
|
641
|
+
* Validate the generated lexicon-${name} artifacts.
|
|
642
|
+
*/
|
|
643
|
+
export async function validate(opts?: { basePath?: string }): Promise<ValidateResult> {
|
|
644
|
+
const basePath = opts?.basePath ?? dirname(dirname(fileURLToPath(import.meta.url)));
|
|
645
|
+
|
|
646
|
+
return validateLexiconArtifacts({
|
|
647
|
+
lexiconJsonFilename: "lexicon-${name}.json",
|
|
648
|
+
requiredNames: REQUIRED_NAMES,
|
|
649
|
+
basePath,
|
|
650
|
+
});
|
|
637
651
|
}
|
|
638
652
|
`;
|
|
639
653
|
}
|